内容简介:在 WPF 程序中,我们有本文将介绍鼠标在窗口之外时获取到的鼠标位置。直接使用 Visual Studio 2019 创建一个空的 WPF 应用程序。默认 .NET Core 版本的 WPF 会带一个文本框和一个按钮。我们现在就用这两个按钮来显示
在 WPF 程序中,我们有 Mouse.GetPosition(IInputElement relativeTo)
方法可以拿到鼠标当前相对于某个 WPF 控件的位置,也可以通过在 MouseMove
事件中通过 e.GetPosition(IInputElement relativeTo)
方法拿到同样的信息。不过,在任意时刻去获取鼠标位置的时候,如果鼠标在窗口之外,将获取到什么点呢?
本文将介绍鼠标在窗口之外时获取到的鼠标位置。
可用于演示的 DEMO
直接使用 Visual Studio 2019 创建一个空的 WPF 应用程序。默认 .NET Core 版本的 WPF 会带一个文本框和一个按钮。我们现在就用这两个按钮来显示 Mouse.GetPosition
获取到的值。
using System; using System.Windows; using System.Windows.Input; using System.Windows.Media; namespace Walterlv.Demo { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); CompositionTarget.Rendering += OnRendering; } private void OnRendering(object sender, EventArgs e) { DebugTextBlock.Text = Mouse.GetPosition(DebugTextBlock).ToString(); DebugButton.Content = Mouse.GetPosition(DebugButton).ToString(); } } }
观察现象
我们运行这个最简单的 Demo,然后不断移动鼠标,可以观察到一旦鼠标脱离窗口客户区,获取到的坐标点将完全固定。
如果不知道客户区是什么,可以阅读下面我的另一篇博客:
在以上图中,我拖动改变了窗口的位置,这时将鼠标移动至离开客户区后,获取到的坐标点又被固定为另一个数值。
推断结论
从上面的动图中以及我实际的测量发现,当鼠标移出窗口的客户区之后,获取鼠标的坐标的时候始终拿到的是屏幕的 (0, 0)
点。如果有多个屏幕,是所有屏幕组合起来的虚拟屏幕的 (0, 0)
点。
验证这一点,我们把窗口移动到屏幕的左上角后,将鼠标移出客户区,左上角的控件其获取到的鼠标位置已经变成了 (0, 31)
,而这个是窗口标题栏非客户区的高度。
原理
Mouse.GetPosition
获取鼠标相对于控件的坐标点的方法在内部的最终实现是 user32.dll 中的 ClientToScreen
。
[DllImport("user32.dll")] static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);
此方法需要使用到一个窗口句柄参数,此参数的含义:
A handle to the window whose client area is used for the conversion.
用于转换坐标点的窗口句柄,坐标会被转换到窗口的客户区部分。
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
如果此方法成功,将返回非零的坐标值;如果失败,将返回 0。
而鼠标在窗口客户区之外的时候,此方法将返回 0,并且经过后面的 ToPoint()
方法转换到控件的坐标下。于是这才得到了我们刚刚观察到的坐标值。
[SecurityCritical, SecurityTreatAsSafe] public static Point ClientToScreen(Point pointClient, PresentationSource presentationSource) { // For now we only know how to use HwndSource. HwndSource inputSource = presentationSource as HwndSource; if(inputSource == null) { return pointClient; } HandleRef handleRef = new HandleRef(inputSource, inputSource.CriticalHandle); NativeMethods.POINT ptClient = FromPoint(pointClient); NativeMethods.POINT ptClientRTLAdjusted = AdjustForRightToLeft(ptClient, handleRef); UnsafeNativeMethods.ClientToScreen(handleRef, ptClientRTLAdjusted); return ToPoint(ptClientRTLAdjusted); }
参考资料
以上所述就是小编给大家介绍的《WPF 程序鼠标在窗口之外的时候,控件拿到的鼠标位置在哪里?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入Linux内核架构
Wolfgang Mauerer / 郭旭 / 人民邮电出版社 / 201005 / 149.00元
众所周知,Linux操作系统的源代码复杂、文档少,对程序员的要求高,要想看懂这些代码并不是一件容易事。本书结合内核版本2.6.24源代码中最关键的部分,深入讨论Linux内核的概念、结构和实现。具体包括进程管理和调度、虚拟内存、进程间通信、设备驱动程序、虚拟文件系统、网络、时间管理、数据同步等方面的内容。本书引导你阅读内核源代码,熟悉Linux所有的内在工作机理,充分展现Linux系统的魅力。 ......一起来看看 《深入Linux内核架构》 这本书的介绍吧!