WPF 使用什么来捕获鼠标和键盘输入?
我使用 SetWindowsHookEx
和 WH_MOUSE_LL
全局(系统范围)过滤某些鼠标点击。问题是它不适用于 WPF 应用程序(所有 WPF 应用程序都会检测鼠标单击,无论我是否指示系统忽略这些单击)。我已经在这里问了一个类似的问题,但我做了一个假设WPF 使用 DirectInput 而不是标准 Windows 消息来检测输入。但确实如此吗?
我已经找到了能够 将鼠标点击注入 WPF 应用程序的代码发送消息
。如果可能的话,那么我认为这在某种程度上意味着 WPF 不使用 DirectInput 进行鼠标输入。但是,为什么无法使用 SetWindowsHookEx
阻止 WPF 应用程序检测鼠标单击呢?
虽然这个问题主要是关于鼠标输入,但我也想知道它对于键盘输入是如何工作的。
示例
我快速创建了以下解决方案来重现奇怪的 WPF 行为。它由 3 个项目组成:
HookTester
StartUp项目,会自动启动另外2个项目,所以您应该主要关注这一个项目。启动时安装鼠标钩子,关闭表单时卸载钩子。WinFormsTest
包含一个带有默认上下文菜单的文本框,您可以在其中测试鼠标右键。当 HookTester 运行时,您不应该能够使用鼠标右键调用上下文菜单。Wpf测试
还包含一个文本框,带有自定义上下文菜单(尽管我也可以使用默认菜单),所以这又是测试鼠标右键的地方。只要 HookTester 正在运行,您就不应该能够调用上下文菜单(使用鼠标右键),但由于某种原因,菜单无论如何都会显示(为什么???)。
警告:当您运行该解决方案时,HookTester 项目将启动,并立即安装挂钩以拒绝任何鼠标右键单击(系统范围内)。您只需关闭 HookTester 表单即可轻松卸载挂钩。谨慎测试。
I globally (system-wide) filter certain mouse clicks using SetWindowsHookEx
and WH_MOUSE_LL
. The problem is it doesn't work for WPF applications (all WPF applications detect mouse clicks whether or not I have instructed the system to ignore these clicks). I've already asked a similar question here, but I made an assumption that WPF uses DirectInput
instead of standard Windows messages for detecting the input. But does it?
I've been able to find a code that was able to inject mouse clicks into WPF applications using SendMessage
. If that's possible, then I think it somehow means WPF does not use DirectInput
for mouse input. But then, why it's not possible to prevent WPF applications from detecting mouse clicks with SetWindowsHookEx
?
Although this question is mainly about the mouse input, I would also like to know how it works for keyboard input as well.
Example
I've quickly created the following solution to reproduce the odd WPF behavior. It consists of 3 projects:
HookTester
StartUp project, automatically launches other 2 projects, so you should be mainly concerned about this one. Installs mouse hook when launched, and uninstalls the hook when you close the form.WinFormsTest
Contains a TextBox with default context menu where you can test the right mouse button. When the HookTester is running, you should not be able invoke the context menu using right mouse button.WpfTest
Contains a TextBox as well, with custom context menu (although I could use default menu as well), so this is again the place to test right mouse button. You should not be able to invoke the context menu (using right mouse button) as long as HookTester is running, but for some reason, the menu will be showed anyway (Why???).
WARNING: When you run the solution, the HookTester project will start and will immediately install the hook to reject any right-buttom mouse clicks (system-wide). You can easily uninstall the hook simply by closing the HookTester form. Test with caution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
即使您尝试设置过滤器,.NET Framework 也可能有一些未记录的 API 将 WPF 的过滤器置于高优先级,根本不允许您的过滤器执行,以确保 WPF 正常工作。
WPF 窗口与普通窗口相同,它们应该能够与预先存在的输入 API 以及新的 API 一起正常工作,以便使 WPF 与远程桌面和其他此类软件一起工作。
更新:
早期的 Windows API 中提供了 Windows Hook,因为当时事件冒泡和事件预览等概念尚不可用,而对于此类实现,挂钩非常有用。 WPF 已经提供了带有预览事件和事件冒泡的事件过滤,这就是可能不支持挂钩的原因。
Hook 并不是 API 的标准部分,因为只有极少数应用程序使用它们。也许你可以在微软发布错误,他们的过滤器不允许你的钩子过滤器。
Even if you try to set filter, .NET Framework may have some undocumented API to put WPF's filter on high priority not allowing your filter to execute at all in order to make sure WPF works correctly.
WPF windows are same as normal window and they are supposed to work correctly with pre-existing input APIs as well as new APIs in order to make WPF work with remote desktop and other such software.
Update:
Windows Hook were provided in earlier windows API because that time the concepts like Event Bubbling and Preview of events were not available and for such implementations hooks were useful. WPF already provides event filtering with Preview events and bubbling of events, and that is the reason hooks may not be supported.
Hooks are not very standard part of API because only very few applications use them. May be you can post bug at Microsoft that their filter is not allowing your hook filter.
(窗口.CreateSourceWindow)。
(HwndSource.初始化)。
委托 Windows 的过程
发送给钩子的消息,由
HwndSource。
HwndSource.InputFilterMessage 表示
将 Windows 消息委托给四个
输入提供者:手写笔、鼠标、
键盘、应用程序命令。
适当的 Windows 消息和
调用 InputManager 来引发输入
元素上的事件。
HwndMouseInputProvider处理WM_MOUSEMOVE、WM_LBUTTONDOWN等消息。所以我认为没有DirectInput用来处理鼠标和键盘输入。
(Window.CreateSourceWindow).
(HwndSource.Initialize).
procedure that delegate Windows
messages to hooks, specified by
HwndSource.
HwndSource.InputFilterMessage that
delegate Windows messages to four
input providers: stylus, mouse,
keyboard, appcommand.
appropriate Windows message and
invokes InputManager to raise input
events on elements.
HwndMouseInputProvider process messages such as WM_MOUSEMOVE, WM_LBUTTONDOWN, etc. So I think there is no DirectInput used to handle mouse and keyboard input.