Windows 7中的鼠标移动 - 左键单击并拖动

时间:2012-04-10 21:56:15

标签: c# .net winforms mouse user32

我试图通过在Windows 7中使用user32.dll模拟鼠标移动和点击来自动绘制类似于绘图的程序。

这就是我拥有的以及如何使用它:

设置

    [DllImport("user32.dll")]
    static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);


    [Flags]
    public enum MouseEventFlags
    {
        LEFTDOWN = 0x00000002,
        LEFTUP = 0x00000004,
        MIDDLEDOWN = 0x00000020,
        MIDDLEUP = 0x00000040,
        MOVE = 0x00000001,
        ABSOLUTE = 0x00008000,
        RIGHTDOWN = 0x00000008,
        RIGHTUP = 0x00000010
    }

    public void LeftMouseDown()
    {
        mouse_event((int)(MouseEventFlags.LEFTDOWN), Cursor.Position.X, Cursor.Position.Y, 0, 0);
    }

    public void LeftMouseUp()
    {
        mouse_event((int)(MouseEventFlags.LEFTUP), Cursor.Position.X, Cursor.Position.Y, 0, 0);
    }

绘图时

            foreach (var contour in contours)
            {
                LeftMouseDown();
                foreach (var point in contour)
                {
                    var x = point.X + offsetX;
                    var y = point.Y + offsetY;
                    Cursor.Position = new Point(x, y);
                    //LeftMouseDown();
                    System.Threading.Thread.Sleep(2);
                }
                LeftMouseUp();
            }

我正在尝试模拟的是鼠标被点击并按住,移动到每个contour中的一堆点,然后放松,然后转到下一个contour

问题是,这只是将鼠标按钮按下以进行第一次移动,然后将其放开。

TL; DR

当以编程方式移动鼠标时,如何让鼠标左键单击?

我正在尝试在第三方应用中模拟绘图。 (Microsoft LINQ的白板,IM客户端。)

2 个答案:

答案 0 :(得分:2)

总结评论记录:这不是预期的结果,因为代码只模拟鼠标点击,而不是鼠标移动。使用Cursor.Position移动光标会直接更改光标位置,绕过Windows输入事件队列。因此,不会向具有焦点的窗口生成任何通知(WM_MOUSEMOVE消息)。

通过将MouseMove()方法添加到使用带有MouseEventFlags.MOVE的mouse_event()的辅助类来修复

答案 1 :(得分:1)

迟到的回复,但我认为你的错误在于调用mouse_event。基本上,mouse_event报告相对鼠标移动(没有MOUSEEVENTF_ABSOLUTE时),但是你传递绝对位置,从而使其行为错误。此外,您应该将光标移动到按下鼠标按钮之前执行鼠标按下的位置。

所以这是我的修复:

// I changed a bit of the method signature, but that doesn't really matter
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
static extern void mouse_event(MouseEventFlags flags, uint dx, uint dy, uint delta, IntPtr extraInfo);

[Flags]
enum MouseEventFlags : uint
{
    Absolute = 0x8000,
    LeftDown = 0x0002,
    LeftUp = 0x0004,
    MiddleDown = 0x0020,
    MiddleUp = 0x0040,
    Move = 0x0001,
    RightDown = 0x0008,
    RightUp = 0x0010,
    Wheel = 0x0800,
    XDown = 0x0080,
    XUp = 0x0100,
    HWheel = 0x1000,
}

public void LeftMouseDown()
{
    // Simulate left down, notice that RELATIVE movement is 0
    mouse_event(MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);
}

public void LeftMouseUp()
{
    // Simulate left up, notice that RELATIVE movement is 0 too
    mouse_event(MouseEventFlags.LeftUp, 0, 0, 0, IntPtr.Zero);
}

移动鼠标时......

foreach (var contour in contours)
{
    // simulate mouse down AFTER cursor is moved to the first point (IMPORTANT!)
    var x = contour[0].X + offsetX;
    var y = contour[0].Y + offsetY;
    Cursor.Position = new Point(x, y);
    LeftMouseDown();
    foreach (var point in contour)
    {
        x = point.X + offsetX;
        y = point.Y + offsetY;
        Cursor.Position = new Point(x, y);
        System.Threading.Thread.Sleep(2);
    }
    // cursor is already at the final position
    LeftMouseUp();
}

附注,通过一些简单的测试,设置Cursor.Position 生成WM_MOUSEMOVE消息。