首页 > 解决方案 > 你如何虚拟地执行鼠标移动和点击 [user32.dll]

问题描述

您如何虚拟执行鼠标移动和点击?

我的意思是,主鼠标不受影响,所以基本上“创建”第二个鼠标,通过设置 x/y 位置(首选 user32.dll)来控制。

我在这里读过一些类似的问题,但答案通常是用你的主鼠标,例如:

DllImport("user32")]
public static extern int SetCursorPos(int x, int y);

^ 这会将您的主鼠标移动到屏幕上的 x&y 位置,我想要的是使用“虚拟鼠标”执行此操作,这样我的主鼠标就不会移动,所以基本上我可以在这个“虚拟鼠标”执行时继续使用我的电脑例如,另一个窗口中的其他内容。

然后使用这个“虚拟鼠标”来执行点击[虚拟键码]

我试过这个:

IntPtr MakeLParam(int x, int y) => (IntPtr)((y << 16) | (x & 0xFFFF));
            
var pointPtr = MakeLParam(900, 1000);//x y cords 
           
IntPtr hWnd = ScreenCapture.FindWindow(null, ScreenCapture.GetWindowName()); //Finds Window 

PostMessage(hWnd, WM_MOUSEMOVE | WM_LBUTTONDOWN | WM_LBUTTONUP, IntPtr.Zero, pointPtr);

[DllImport("User32.dll")]
        public static extern Int32 PostMessage(
            IntPtr hWnd,               // handle to destination window
            int Msg,                // message
            IntPtr wParam,             // first message parameter
            IntPtr lParam);            // second message parameter

但是什么都没有发生,我的猜测是 WM_MOUSEMOVE 无法正常工作

public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_COMMAND = 0x111;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_LBUTTONDBLCLK = 0x203;
        public const int WM_RBUTTONDOWN = 0x204;
        public const int WM_RBUTTONUP = 0x205;
        public const int WM_RBUTTONDBLCLK = 0x206;
        public const int WM_MOUSEMOVE = 0x0200;

更新,我想我解决了一些问题!

在阅读了有关 PostMessage /SendInput 的更多信息后,我发现“应用程序窗口”可以有“应用程序窗口”的层,所以我使用 ispy++ 来检查它,是的,该程序还有另一个我想点击的层。

所以为了解决这个问题,我使用了我想点击的窗口的类名以及窗口名,下面是一个示例代码:

 public static bool ClickTest()
        {
            IntPtr MakeLParam(int x, int y) => (IntPtr)((y << 16) | (x & 0xFFFF));//Just converts x&y to InPtr lParam

            IntPtr WindowhWid = ScreenCapture.FindWindow(null, ScreenCapture.GetWindowName()); //Gets the window hWid
            var ClasshWid = FindWindowEx(WindowhWid, IntPtr.Zero, "Classname", null); //Gets the Class hWid using WindowhWid AND the Class name (Need to find a way to get the classname using process list)

            PostMessage(ClasshWid, WM_LBUTTONDOWN | WM_LBUTTONUP, 0, MakeLParam(938, 1011));//Finally sends it to the classhWid

            return true;
        }
        

使用这两个函数

[DllImport("User32.dll")]
        public static extern int FindWindowEx(
            IntPtr hwndParent, 
            IntPtr hwndChildAfter,
            string strClassName,
            string strWindowName);

[DllImport("User32.dll")]
        public static extern Int32 PostMessage(
            int hWnd,               // handle to destination window
            int Msg,                // message
            int wParam,             // first message parameter
            IntPtr lParam);            // second message parameter

请注意,如果应用程序窗口被最小化,它不会点击,但如果窗口在另一个应用程序窗口后面,它会点击!

X & Y 也是屏幕 X & Y 而不是应用程序 X & Y !

现在问题仍然存在,为什么在应用程序窗口最小化时它不起作用?

点击不会去任何地方,而是应用程序,所以在应用程序最小化时它不应该工作吗?

标签: c#winapi

解决方案


它可能不是您需要做的事情和您所关心的事情,但AutoIT Dll以最简单的方式提供了大量随时可用的自动化功能。由于您依赖于 Windows DLL,因此它是完美的。

如果您仍然在自己的方式上 user32.dll 然后检查Low level hook,这就是我使用的。

不过,我强烈推荐 AutoIT dll,它可以为您节省大量时间来猜测无法正确响应的 windows 消息发生了什么


推荐阅读