在C#中移动鼠标(坐标单位)

5

我正在尝试制作一个类似于Teamviewer的软件,可以让一个人查看另一个人的屏幕并进行点击等操作。无论如何,我已经完成了大部分套接字相关的工作,但是我不知道如何使鼠标点击正常工作。以下是我在网上找到的移动鼠标程序代码:

  public static class VirtualMouse
{
    // import the necessary API function so .NET can
    // marshall parameters appropriately
    [DllImport("user32.dll")]
    static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

    // constants for the mouse_input() API function
    private const int MOUSEEVENTF_MOVE = 0x0001;
    private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
    private const int MOUSEEVENTF_LEFTUP = 0x0004;
    private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
    private const int MOUSEEVENTF_RIGHTUP = 0x0010;
    private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
    private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
    private const int MOUSEEVENTF_ABSOLUTE = 0x8000;


    // simulates movement of the mouse.  parameters specify changes
    // in relative position.  positive values indicate movement
    // right or down
    public static void Move(int xDelta, int yDelta)
    {
        mouse_event(MOUSEEVENTF_MOVE, xDelta, yDelta, 0, 0);
    }


    // simulates movement of the mouse.  parameters specify an
    // absolute location, with the top left corner being the
    // origin
    public static void MoveTo(int x, int y)
    {
        mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
    }


    // simulates a click-and-release action of the left mouse
    // button at its current position
    public static void LeftClick()
    {
        mouse_event(MOUSEEVENTF_LEFTDOWN, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
    }
}

现在我想使用MoveTo方法移动鼠标,但是它需要非常高的数字才能进行任何移动。有没有办法将此处的移动坐标与屏幕上的像素位置匹配?如果这个问题似乎很明显,那么对不起,但我已经搜索了将近一个小时,找不到任何关于鼠标x和y位置所使用的单位的讨论,因此我无法设置任何公式来匹配一个面板上的点击到用户屏幕上的点击。

3
Cursor.Position 看起来很有前途。 - chris
1个回答

7

来自Microsoft文档

如果指定了MOUSEEVENTF_ABSOLUTE值,则dx和dy包含0到65,535之间的标准化绝对坐标。事件过程将这些坐标映射到显示表面上。 坐标(0,0)映射到显示表面的左上角,(65535,65535)映射到右下角。

您可以使用它将像素输入转换为所需值,例如:

var inputXinPixels = 200;
var inputYinPixels = 200;
var screenBounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
var outputX = inputXinPixels * 65535 / screenBounds.Width;
var outputY = inputYinPixels * 65535 / screenBounds.Height;
MoveTo(outputX, outputY);

请记住,这可能不适用于多个监视器。还要注意文档中所说的:
此函数已过时。请改用SendInput补充:如J3soon所指出,上述公式可能不是最好的。根据为AutoHokey所做的研究,以下代码内部效果更好:
var outputX = (inputXinPixels * 65536 / screenBounds.Width) + 1;
var outputY = (inputYinPixels * 65536 / screenBounds.Height) + 1;

参考AutoHotkey源代码


如果我处在你的位置,我会使用 Cursor.Position。以下代码按预期工作:
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(200, 200);

是的,它将鼠标指针放置在屏幕坐标(200, 200)像素处 [在LinqPad上测试过]。
补充说明:我查看了System.Windows.Forms.Cursor.Position在Windows上Mono内部使用的内容。至少在Windows上的Mono中,它是调用SetCursorPos。不需要奇怪的坐标转换。

1
在我的情况下,inputXinPixels * 65536 / SCREEN_WIDTH + 1 的效果更好,这也被用于AutoHotKey - J3soon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接