如何在WPF中获取当前鼠标屏幕坐标?

83

如何获取鼠标在屏幕上的当前坐标?我只知道 Mouse.GetPosition() 可以获取元素的鼠标位置,但我想要不使用元素获取坐标。


鼠标坐标相对于什么?屏幕坐标,还是相对于窗口? - Fredrik Hedblad
3
我表示屏幕上的鼠标位置。 - Prince OfThief
System.Windows.Forms.Cursor.Position - vinsa
9个回答

94

或者在纯WPF中使用PointToScreen

以下是示例帮助方法:

// Gets the absolute mouse position, relative to screen
Point GetMousePos() => _window.PointToScreen(Mouse.GetPosition(_window));

将代表 Visual 当前坐标系的 Point 转换为屏幕坐标中的 Point。这与鼠标位置有什么关系? - Jonas Elfström
19
Mouse.GetPosition 返回一个 Point,而 PointToScreen 将该点转换为屏幕坐标。 - erikH
你好 @erikH,能否更新链接?它已经失效了。 - Patrick D'Souza
谢谢Patrick。现在又好了。(MSDN改变了一些东西...) - erikH

84

在Rachel的回答之后,这里有两种方法可以在WPF中获取鼠标屏幕坐标。

1.使用Windows Forms。 添加对System.Windows.Forms的引用。

public static Point GetMousePositionWindowsForms()
{
    var point = Control.MousePosition;
    return new Point(point.X, point.Y);
}

2.使用Win32

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);

[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
    public Int32 X;
    public Int32 Y;
};
public static Point GetMousePosition()
{
    var w32Mouse = new Win32Point();
    GetCursorPos(ref w32Mouse);

    return new Point(w32Mouse.X, w32Mouse.Y);
}

3
如果你使用原始的X和Y坐标来设置窗口位置,那么即使你的DPI设置不是100%(96dpi),它也无法正常工作。尽管如此,上一个回答已经给出了正确答案! - user195275
你的评论完全正确,这不应该被标记为此问题的正确答案! - Arash
这也是一个 Windows Forms 的答案,不是 WPF 答案。这不是问题的答案。 - Mike

34

您想要相对于屏幕还是应用程序的坐标?

如果是在应用程序内部,只需使用:

Mouse.GetPosition(Application.Current.MainWindow);

如果没有的话,我相信你可以添加对 System.Windows.Forms 的引用,然后使用:

System.Windows.Forms.Control.MousePosition;

2
必须使用 System.Windows.Forms.Control.MousePosition。 - Prince OfThief
error CS0234: The type or namespace name 'Control' does not exist in the namespace 'System.Windows.Forms' (are you missing an assembly reference?) - Jonathan Tuzman

25

如果您在不同的分辨率、使用多个显示器的电脑上尝试了很多这些答案,您可能会发现它们无法可靠地工作。这是因为您需要使用转换来获取相对于当前屏幕的鼠标位置,而不是整个视图区域(包括所有显示器)。类似于这样的代码...(其中“this”是一个WPF窗口)。

var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
var mouse = transform.Transform(GetMousePosition());

public System.Windows.Point GetMousePosition()
{
    var point = Forms.Control.MousePosition;
    return new Point(point.X, point.Y);
}

1
非常感谢!我在高分辨率屏幕上遇到了问题,但是转换似乎非常有效。 - mdiehl13
@mdiehl13 不用担心 :) 很高兴你发现我的转换正常工作 - Alexandru
1
@mdiehl13 显然,很多人只测试基本情况。对于测试不同分辨率等方面的内容,点个赞 :) - Alexandru

8
这可以在不使用表单或导入任何DLL的情况下正常工作:
   using System.Windows;
   using System.Windows.Input;

    /// <summary>
    /// Gets the current mouse position on screen
    /// </summary>
    private Point GetMousePosition()
    {
        // Position of the mouse relative to the window
        var position = Mouse.GetPosition(Window);

        // Add the window position
        return new Point(position.X + Window.Left, position.Y + Window.Top);
    }

5
您可以使用TimerDispatcher(WPF计时器模拟器)和Windows“钩子”结合使用,从操作系统中捕获光标位置。
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetCursorPos(out POINT pPoint);

Point是一个轻量级的结构体,它只包含X和Y字段。

    public MainWindow()
    {
        InitializeComponent();

        DispatcherTimer dt = new System.Windows.Threading.DispatcherTimer();
        dt.Tick += new EventHandler(timer_tick);
        dt.Interval = new TimeSpan(0,0,0,0, 50);
        dt.Start();
    }

    private void timer_tick(object sender, EventArgs e)
    {
        POINT pnt;
        GetCursorPos(out pnt);
        current_x_box.Text = (pnt.X).ToString();
        current_y_box.Text = (pnt.Y).ToString();
    }

    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }

这个解决方案还可以解决参数读取过于频繁或不够频繁的问题,因此您可以自己进行调整。但是请记住,WPF方法过载只接受一个表示ticks而不是milliseconds的参数。

TimeSpan(50); //ticks

3
如果您正在寻找一行代码,这个很不错。
new Point(Mouse.GetPosition(mWindow).X + mWindow.Left, Mouse.GetPosition(mWindow).Y + mWindow.Top)
< p > + mWindow.Left + mWindow.Top 确保当用户拖动窗口时,位置仍然正确。


1

Mouse.GetPosition(mWindow)会给你相对于你选择的参数的鼠标位置。

mWindow.PointToScreen()将该位置转换为相对于屏幕的点。

因此,假设mWindow是一个窗口(实际上,任何继承自System.Windows.Media.Visual类的类都将具有此函数),mWindow.PointToScreen(Mouse.GetPosition(mWindow))会给出相对于屏幕的鼠标位置。如果您在WPF窗口类中使用此函数,则this应该有效。


0

我想使用这段代码

Point PointA;
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e) {
    PointA = e.MouseDevice.GetPosition(sender as UIElement);
}

private void Button_Click(object sender, RoutedEventArgs e) {
    // use PointA Here
}

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