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

如何获得当前鼠标在屏幕上的协调? 我只知道得到元素的 mousePosition 的 Mouse.GetPosition(),但是我想不使用元素得到协调。

153587 次浏览

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

如果它在应用程序中,只需使用:

Mouse.GetPosition(Application.Current.MainWindow);

如果没有,我相信你可以添加一个参考 System.Windows.Forms和使用:

System.Windows.Forms.Control.MousePosition;

跟进 Rachel 的回答。
这里有两种方法,你可以得到鼠标屏幕坐标在 WPF。

1. 使用 Windows 窗体。添加对 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);
}

或者在纯 WPF 中使用 PointToScreen

示例辅助方法:

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

如果你在不同的分辨率、有多台显示器的计算机上尝试了很多这样的答案,你可能会发现它们不能可靠地工作。这是因为您需要使用一个转换来获得相对于当前屏幕的鼠标位置,而不是包含所有显示器的整个观看区域。类似这样的东西... (其中“ 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);
}

这种方法无需使用表单或导入任何 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);
}

您可以结合使用 TimerDispatcher (WPF Timer 模拟)和 Windows“ Hooks”来从操作系统捕获光标位置。

    [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT pPoint);

点是一个轻的 struct。它只包含 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

如果您正在寻找一个1行,这样做很好。

new Point(Mouse.GetPosition(mWindow).X + mWindow.Left, Mouse.GetPosition(mWindow).Y + mWindow.Top)

+ mWindow.Left+ mWindow.Top确保位置正确,即使用户拖动窗口也是如此。

Mouse.GetPosition(mWindow)提供相对于所选参数的鼠标位置。 mWindow.PointToScreen()将位置转换为相对于屏幕的一个点。

因此,假设 mWindow是一个窗口(实际上,从 System.Windows.Media.Visual派生的任何类都有这个函数) ,如果在 WPF 窗口类中使用这个函数,那么 this应该可以工作。

我想用这个密码

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
}