1

我有一个多线程应用程序,需要能够同时执行多个鼠标单击。

我有一个IntPtr intptr需要向其发送鼠标点击的进程。我试图在网上找到这些信息,并且有一些我尝试过的例子。但我没有让他们中的任何一个工作。

据我了解,解决我的问题的正确方法是使用该功能 SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

hWnd 是进程的 IntPtr。Msg 是想要的操作,我想要左键单击,int WM_LBUTTONDBLCLK = 0x0203; IntPtr wParam 对这个问题没有兴趣(据我了解)并且单击的坐标在 lParam 中。我构造 lParam 像,

Int32 word = MakeLParam(x, y);

private int MakeLParam(int LoWord, int HiWord)
     {
         return ((HiWord << 16) | (LoWord & 0xffff));
     }

但正如你可能理解的那样,我无法让它工作。我的第一个问题是,坐标是在这个过程的窗口内还是绝对屏幕坐标?我的第二个问题,我做错了什么?

4

5 回答 5

3

我最近试图在 C# 中模拟鼠标点击,我写了这个小助手类来做到这一点:

public static class SimInput
{
    [DllImport("user32.dll")]
    static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);

    [Flags]
    public enum MouseEventFlags : uint
    {
        Move = 0x0001,
        LeftDown = 0x0002,
        LeftUp = 0x0004,
        RightDown = 0x0008,
        RightUp = 0x0010,
        MiddleDown = 0x0020,
        MiddleUp = 0x0040,
        Absolute = 0x8000
    }

    public static void MouseEvent(MouseEventFlags e, uint x, uint y)
    {
        mouse_event((uint)e, x, y, 0, UIntPtr.Zero);
    }

    public static void LeftClick(Point p)
    {
        LeftClick((double)p.X, (double)p.Y);
    }

    public static void LeftClick(double x, double y)
    {
        var scr = Screen.PrimaryScreen.Bounds;
        MouseEvent(MouseEventFlags.LeftDown | MouseEventFlags.LeftUp | MouseEventFlags.Move | MouseEventFlags.Absolute,
            (uint)Math.Round(x / scr.Width * 65535),
            (uint)Math.Round(y / scr.Height * 65535));
    }

    public static void LeftClick(int x, int y)
    {
        LeftClick((double)x, (double)y);
    }
}

坐标是 65535 的一小部分,这有点奇怪,但是这个类会为你处理。

于 2012-05-18T22:54:44.613 回答
0

我不是 100% 确定我了解您要完成的工作。但是,如果您想模拟鼠标输入,那么我建议您使用SendInput API。

您可以提供要插入到输入流中的输入数组。

另请参阅:PInvoke 参考

于 2012-05-18T22:24:41.257 回答
0

我不明白为什么有人想同时发送多个鼠标点击。如果是为了测试你的 GUI,那就是错误的测试。没有人可以在同一时间空间内多次物理点击某物。

但是回到你的问题,使用 SendMessage 不会帮助你,因为它基本上是一个阻塞调用。即使您尝试使用 PostMessage,您也无法完成同时点击,因为消息队列是从 UI 线程中抽取的,并且消息会弹出并按顺序处理。

于 2012-05-18T22:42:33.667 回答
0

我使用此代码单击句柄中的左按钮

public static void MouseLeftClick(Point p, int handle = 0)
{
    //build coordinates
    int coordinates = p.X | (p.Y << 16);
    //send left button down
    SendMessage(handle, 0x201, 0x1, coordinates);
    //send left button up
    SendMessage(handle, 0x202, 0x1, coordinates);
}

如果您在调用时未设置句柄 - 然后它将点击发送到桌面,因此坐标应该是整个屏幕,如果您要设置句柄,那么消息将被发送到句柄的窗口,您应该为窗口设置坐标。

于 2012-05-18T22:49:19.440 回答
0

只使用 VirtualMouse 怎么样?我在 C# 中使用它,效果很好。

    public partial class Form1 : Form
    {
        private VirtualMouse vm = new VirtualMouse();
        public Form1()
        {
            InitializeComponent();
        }
        private void MouseClickHere(Point myPoint)
        {
            vm.ClickIt(myPoint, 150);
        }
        private void Clicker()
        {
             MouseClickHere(new Point(250,350));
        }
    }
于 2021-04-03T21:53:01.817 回答