c# Mouse click simulation to hwnd at x/y position - c#

at the last 3 Days I found a lot of code for simulating mouse clicks to other windows. but none of them has worked.
I have the window handle hwnd and the X/Y position (pixel) where the click has to be.
The X/Y position is the position inside the window.
The best code I've found is this:
public void click(IntPtr hWnd, int x, int y)
{
RECT rec = new RECT();
GetWindowRect(hWnd, ref rec);
int newx = x - rec.Left;
int newy = y - rec.Top;
SendMessage(hWnd, WM_LBUTTONDOWN, 1, ((newy << 0x10) | newx));
SendMessage(hWnd, WM_LBUTTONUP, 0, ((newy << 0x10) | newx));
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr A_0, int A_1, int A_2, int A_3);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
But it does not work 100% correctly.
It simulates a mouseclick at the correct window, but at the position of my real cursor.
And after this click my mouse jumps to a random position on the screen.
I hope someone has a working code and a small description how it works.
Thanks

Use this code to simulate the left mouse click in a certain position
//This is a replacement for Cursor.Position in WinForms
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
//This simulates a left mouse click
public static void LeftMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}

Related

Creating a 'Ghost Mouse' to simulate mouse clicks

I know there are already a million threads about this, but I've spent countless hours trying to find a solution and i'm hoping I can find it here instead.
My goal is to create a 'Ghost mouse', meaning that I want to be able to simulate mouse clicks on a certain position in a minimized window, without moving my own cursor our mouse. I want to be able to browse the internet and click on other stuff, while the program does its own thing. This is a feature that many game bots have, but my intention is not to create a bot, but only to experience with.
So far i've managed to simulate mouse clicks, but with my actual mouse.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
public static void LeftClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
static void Main(string[] args)
{
System.Threading.Thread.Sleep(5000);
Point pt = new Point(1259, 560);
Cursor.Position = pt;
LeftClick();
}
As far as I know, calling mouse_event will not click in minimized windows.
You have to use SendMessage WinApi for this.
First, acquire a handle for the process, either using OpenProcess or Process.GetProcessesByName(processName).First().MainWindowHandle, then you may use the following code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
public static IntPtr makeLParam(int x, int y)
{
return (IntPtr)((y << 16) | x);
}
public static void sendMouseClick(IntPtr handle, int x, int y)
{
SendMessage(handle, WM_LBUTTONDOWN, (IntPtr)1, makeLParam(x, y));
SendMessage(handle, WM_LBUTTONUP, (IntPtr)1, makeLParam(x, y));
}
Please note that this code is a bit old and might not still work. Also, keep in mind the game protections prevents acquiring handles for the game process. In addition, some games might query the mouse position from the windows rather than using the ones provided with SendMessage

C# How to move mouse(cursor) position while its hidden...?

My cursor.position function works, but when the cursor is focused in a window and hidden ( for example in a game when the cursor hides itself ) it doesn't move...
Any solution?
My code:
Cursor.Position = new Point(Cursor.Position.X + Xvariable, Cursor.Position.Y + Yvariable);
You can test this one
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
private const int MOUSEEVENTF_MOVE = 0x0001;
public static void Move(int xDelta, int yDelta)
{
mouse_event(MOUSEEVENTF_MOVE, xDelta, yDelta, 0, 0);
}
Usage Move(830, 160);
Reference

What makes this click through?

I'm trying to figure out how this code works but I just can not figure out what makes it click through.
Yes, this code is not mine since i'm trying to learn/understand it.
Assume I want the tranparancy but not the click through what needs to be changed and why?
I have been over the Windows styles pages over and over and still can not get my head around the click through part.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class TransparentWindow : MonoBehaviour
{
[SerializeField]
private Material m_Material;
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const int HWND_TOPMOST = -1;
void Start()
{
#if !UNITY_EDITOR // You really don't want to enable this in the editor..
int fWidth = Screen.width;
int fHeight = Screen.height;
var margins = new MARGINS() { cxLeftWidth = -1 };
var hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
// Transparent windows with click through
SetWindowLong(hwnd, -20, 524288 | 32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes(hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
DwmExtendFrameIntoClientArea(hwnd, ref margins);
#endif
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
}
This function:
SetWindowLong(hwnd, -20, 524288 | 32);
does the trick. Windows implements the rule that Mircosoft made which is that a window that is transparent to the user must be transparent to the mouse.
With the transparency bit set WS_EX_TRANSPARENT the window becomes transparent to mouse too and click passes to the painted layer behind the transparent window.
You need not understand but make use of this 'OS feature' which was probably implemented to cover for something else.
Read this article about the subject and this answer that explains the parameters

GetWindowRect returning 0

I am trying to find the window size of a new process that I am opening, but it is returning 0 for the height and width. Here is my code:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
static void Main(string[] args)
{
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files (x86)\FirstClass\fcc32.exe";
//C:\Program Files (x86)\FirstClass\fcc32.exe
process.Start();
Console.WriteLine(process.HandleCount);
IntPtr hWnd = process.MainWindowHandle;
RECT rect = new RECT();
process.WaitForInputIdle();
GetWindowRect(hWnd, ref rect);
int width = rect.Right - rect.Left;
int height = rect.Bottom - rect.Top;
Console.WriteLine("Height: " + height + ", Width: " + width);
Console.ReadLine();
}
Thanks for the answers everybody, but the actual problem was that I was doing
IntPtr hWnd = process.MainWindowHandle;
before the process window had actually had a chance to open.
The signature is wrong it should be:
[DllImport("user32.dll", SetLastError=true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
change calling code accordingly:
RECT rect;
process.WaitForInputIdle();
GetWindowRect(hWnd, out rect);

.Net correspondings of WinApi TabControl styles

Within each tab, the control centers the icon and label, placing the icon to the left of the label. In WinApi you can force the icon to the left, leaving the label centered, by specifying the TCS_FORCEICONLEFT style. You can left-align both the icon and label by using the TCS_FORCELABELLEFT style.
How can I make the same in c#?
There is similar question, but those solution does not work for me, despyte I use Edward's advice.
In class derived from TabControl (I need draggable tabs, but now while tab is dragged the alignment of its label breaks since I set the SizeMode to Fixed to get tabs the same width and properly dragging):
[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
protected static extern bool SetWindowLong32(IntPtr ptr, int index, int value);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
protected static extern bool SetWindowLongPtr64(IntPtr ptr, int index, int value);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
protected static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
private const int GWL_STYLE = -16;
private const int TCS_FORCELABELLEFT = 0x20;
protected static bool SetWindowLong(IntPtr ptr, int index, int value)
{
if (IntPtr.Size == 4)
{
return SetWindowLong32(ptr, index, value);
}
return SetWindowLongPtr64(ptr, index, value);
}
and in TabControl constructor:
SetWindowLong(Handle, GWL_STYLE, TCS_FORCELABELLEFT);
var SWP_FRAMECHANGED = 0x20;
var SWP_NOMOVE = 0x2;
var SWP_NOSIZE = 0x1;
var SWP_NOZORDER = 0x4;
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
I'm aware it's possible use owner-drawn mode, but I don't know how can i use the system style changing only necessary elements.
If you want to just call SetWindowLong, try
[DllImport("user32.dll")]
static extern bool SetWindowLong(IntPtr ptr, int index, int value);
If you are targeting 32-/64-bit platforms, this SO answer might throw some light on how to invoke the function properly.

Categories

Resources