I want to simulate a left-click at the window (background) x/y coordinates.
I have searched and found a lot of stuff to simulate mouseclicks to other windows but it does not work 100% well.
My code:
private const int WM_LBUTTONDOWN = 0x201; //Left mousebutton down
private const int WM_LBUTTONUP = 0x202; //Left mousebutton up
[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
public static extern bool PostMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
public void SimulateMouseLeft(IntPtr hwnd, int x,int y)
{
int coordinates = x | (y << 16);
//PostMessage(hwnd, WM_LBUTTONDOWN, IntPtr.Zero, (IntPtr)coordinates);
//PostMessage(hwnd, WM_LBUTTONUP, IntPtr.Zero, (IntPtr)coordinates);
PostMessage(hwnd, WM_LBUTTONDOWN, (IntPtr)0x1, (IntPtr)coordinates);
PostMessage(hwnd, WM_LBUTTONUP, (IntPtr)0x1, (IntPtr)coordinates);
//send left button up
//PostMessage(hwnd, 0x202, (IntPtr)0x1, (IntPtr)coordinates);
}
If I start this code, and simulate a click to another window, then the other window gets a left click but not at x/y. The click is at the same position then my mouse is and after the click my mouse jumps to another position on the screen.
Thanks for your help!
Related
How can I set the Delta parameter of the WM_MOUSEWHEEL message and send the message to a Windows using PostMessage?
My code:
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
const uint WM_MOUSEWHEEL = 0x020A;
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
Now I'm using it like this:
IntPtr hwnd1;
hwnd1 = FindWindow(null, "NoxPlayer");
Point location = new Point(1205,411);
PostMessage(hwnd1, WM_MOUSEWHEEL, 0, MAKELPARAM(location.X, location.Y));
When I do it like that I have:
The Windows doesn't scroll because delta is 0.
The WHEEL_DELTA is the default value of a mouse wheel increment (for mouse controllers with no freely-rotating wheel). This value is returned by SystemInformation.MouseWheelScrollDelta.
It's usually set to 120, but it can be a different value.
When the Delta value is positive, it indicates that the mouse wheel is rotated forward, causing a Window to scroll upwards, the opposite when Delta is negative.
In the code sample, directionUp and directionDown determine this direction.
The Delta can be set to a fraction or a multiple of the base increment (can be used to fine-tune the scrolling). See the Docs about WM_MOUSEWHEEL for more information.
In the example, the wheel increment is divided in half (the float multiplier argument of the MAKEWPARAM macro is set to .5f).
The Window identified by [Handle] doesn't need to be activated (it doesn't need to be the Foreground Window).
The Cursor position represents Screen coordinates. The application should be DpiAware to handle Cursor positions and Screen coordinates correctly.
See the notes about the VirtualScreen and how DpiAwareness is involved here:
Using SetWindowPos with multiple monitors.
int directionUp = 1;
int directionDown = -1;
// Scrolls [Handle] down by 1/2 wheel rotation with Left Button pressed
IntPtr wParam = MAKEWPARAM(directionDown, .5f, WinMsgMouseKey.MK_LBUTTON);
IntPtr lParam = MAKELPARAM(Cursor.Position.X, Cursor.Position.Y);
PostMessage([Handle], WM_MOUSEWHEEL, wParam, lParam);
internal const uint WM_MOUSEWHEEL = 0x020A;
[Flags]
public enum WinMsgMouseKey : int
{
MK_NONE = 0x0000,
MK_LBUTTON = 0x0001,
MK_RBUTTON = 0x0002,
MK_SHIFT = 0x0004,
MK_CONTROL = 0x0008,
MK_MBUTTON = 0x0010,
MK_XBUTTON1 = 0x0020,
MK_XBUTTON2 = 0x0040
}
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
internal static IntPtr MAKEWPARAM(int direction, float multiplier, WinMsgMouseKey button)
{
int delta = (int)(SystemInformation.MouseWheelScrollDelta * multiplier);
return (IntPtr)(((delta << 16) * Math.Sign(direction) | (ushort)button));
}
internal static IntPtr MAKELPARAM(int low, int high)
{
return (IntPtr)((high << 16) | (low & 0xFFFF));
}
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
I want to simulate a mouseclick at a specific position inside a window that is hidden. So no maximizing the window or moving the mouse. I just want to send the right message.
Now I tried something like this
DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
static int WM_LBUTTONDOWN = 0x0201;
static int WM_LBUTTONUP = 0x0202;
private static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
public static void test()
{
int windowPtr = FindWindow(null, "Calculator");
Console.WriteLine("pointer: " + windowPtr);
int x = 260;
int y = 180;
IntPtr lParam = MakeLParam(x, y);
IntPtr windowPointer = new IntPtr(windowPtr);
PostMessage(windowPointer, WM_LBUTTONDOWN, IntPtr.Zero, lParam);
PostMessage(windowPointer, WM_LBUTTONUP, IntPtr.Zero, lParam);
}
I expected this program to click the 8 on the calculator ( if you set it to scientific ), but it doesn't do that.
How can I simulate that click? Please don't suggest finding the windows-control-element for the "8"-Button, this is not what I am trying to do here.
I am trying to click on 'OK' button on a message box of C# windows form using winapi. Below is the code that I am working on.
private const int WM_CLOSE = 16;
private const int BN_CLICKED = 245;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(int hWnd, int msg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
//this works
hwnd = FindWindow(null, "Message");
if(hwnd!=0)
SendMessage(hwnd, WM_CLOSE, 0, IntPtr.Zero);
//this doesn't work.
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "Button", "ok");
SendMessage((int)hwndChild, BN_CLICKED, 0, IntPtr.Zero);
Though i get a value in hwndChild, it is not recognising BN_CLICKED.
I am not sure what am I missing. any help?
I am trying to close the message box button of another application and this is what I am doing. But, I m still missing something.
IntPtr hwndChild = IntPtr.Zero;
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero,' '"Button", "OK");
SendMessage((int)hwndChild, WM_COMMAND, (BN_CLICKED '<<16) | IDOK, hwndChild);
BN_CLICKED is not a message. You need to send a WM_COMMAND message containing the BN_CLICKED notification and the button ID in the wParam and the button handle in lParam.
The parent window of the button receives this notification code
through the WM_COMMAND message.
private const uint WM_COMMAND = 0x0111;
private const int BN_CLICKED = 245;
private const int IDOK = 1;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
SendMessage(hwndChild, WM_COMMAND, (BN_CLICKED << 16) | IDOK, hwndChild);
Finallu, this works for me.
First click probably activates the window and second click clicks the button.
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
I believe what I'm trying to do is fairly simple but have been stuck for hours googling already.
I have a windows Form with a button. When I press the button I want to perform a rightclick with my mouse on coordinate 50, 50. This is outside the form so I think it should be done with a windowhook.
Please help.
You should use not hook, but WinApi.
You need one of 2 methods from USER32.DLL (read about different in MSDN):
[DllImport("user32.dll")]
private static extern bool SendMessage(int hnd, Messages msg, int wParam, uint lParam);
[DllImport("user32.dll")]
private static extern bool PostMessage(int hWnd, Messages msg, int wParam, int lParam);
Messages is a enum, here it is:
enum Messages
{
WM_LBUTTONDOWN = 0x201,
WM_LBUTTONUP = 0x202,
WM_RBUTTONDOWN = 0x204,
WM_RBUTTONUP = 0x205
}
And with this methods you should send special messages to hWND equals to 0, which means sending messages to Desktop.
Here methods which will help you:
public static void MouseLeftClick(Point p)
{
int coordinates = p.X | (p.Y << 16);
PostMessage(0, Messages.WM_LBUTTONDOWN, 0x1, coordinates);
PostMessage(0, Messages.WM_LBUTTONUP, 0x1, coordinates);
}
public static void MouseRightClick(Point p)
{
int coordinates = p.X | (p.Y << 16);
PostMessage(0, Messages.WM_RBUTTONDOWN, 0x1, coordinates);
PostMessage(0, Messages.WM_RBUTTONUP, 0x1, coordinates);
}
By changing 0 to Handle of any Window you can press left or right button in any Window you want.