【问题标题】:What does WPF use to capture mouse and keyboard input?WPF 使用什么来捕获鼠标和键盘输入?
【发布时间】:2011-06-29 11:58:57
【问题描述】:

我使用SetWindowsHookExWH_MOUSE_LL 全局(系统范围)过滤某些鼠标点击。问题是它不适用于 WPF 应用程序(无论我是否指示系统忽略这些点击,所有 WPF 应用程序都会检测到鼠标点击)。我已经问过similar question here,但我假设 WPF 使用DirectInput 而不是标准的 Windows 消息来检测输入。但真的吗?

我已经找到了能够inject mouse clicks into WPF applications using SendMessage 的代码。如果这是可能的,那么我认为这在某种程度上意味着 WPF 不使用DirectInput 进行鼠标输入。但是,为什么无法阻止 WPF 应用程序使用SetWindowsHookEx 检测鼠标点击?

虽然这个问题主要是关于鼠标输入的,但我也想知道它对键盘输入的作用。

示例

我快速创建了以下解决方案来重现奇怪的 WPF 行为。它由 3 个项目组成:

  • HookTester
    启动项目,自动启动其他2个项目,所以你应该主要关注这个。启动时安装鼠标钩子,关闭窗体时卸载鼠标钩子。

  • WinFormsTest
    包含一个带有默认上下文菜单的文本框,您可以在其中测试鼠标右键。当 HookTester 运行时,您应该无法使用鼠标右键调用上下文菜单。

  • WpfTest
    还包含一个 TextBox,带有自定义上下文菜单(尽管我也可以使用默认菜单),所以这又是测试鼠标右键的地方。只要 HookTester 正在运行,您就不能调用上下文菜单(使用鼠标右键),但出于某种原因,无论如何都会显示菜单(为什么???)。

警告:当您运行解决方案时,HookTester 项目将启动并立即安装挂钩以拒绝任何鼠标右键单击(系统范围内)。您只需关闭 HookTester 表单即可轻松卸载挂钩。谨慎测试。

下载 SO5036143.ZIP: mirror 1, mirror 2

【问题讨论】:

    标签: .net wpf input hook mouse-hook


    【解决方案1】:
    • WPF 窗口创建 HwndSource (Window.CreateSourceWindow)。
    • HwndSource 创建 HwndWrapper (HwndSource.Initialize)。
    • HwndWrapper 创建带窗口的 Win32 窗口 委托 Windows 的过程 到钩子的消息,由 HwndSource。
    • 一个钩子是 HwndSource.InputFilterMessage 表示 将 Windows 消息委托给四个 输入提供者:手写笔、鼠标、 键盘,应用命令。
    • 提供程序解析 适当的 Windows 消息和 调用 InputManager 来提高输入 元素上的事件。

    HwndMouseInputProvider处理WM_MOUSEMOVE、WM_LBUTTONDOWN等消息。所以我认为没有DirectInput用来处理鼠标和键盘输入。

    【讨论】:

    • 谢谢,很棒的信息!但是,当 WPF 使用标准 Windows 消息的包装器时,低级挂钩怎么可能不起作用?它在任何非 WPF 应用程序中运行良好,但使用 WPF 的应用程序的行为不如预期(我可以正确检测 WPF 应用程序中的鼠标事件,但我无法取消该事件,即使它适用于任何其他非WPF 应用程序)。
    • 也许你应该发布一个例子?顺便说一句,如果你想管理 WPF 输入,你应该看看 InputManager 类。
    • 谢谢。我发现您的 WM_RBUTTONUP 常量值是错误的。它应该是 0x205。而且 WPF 应用程序中不会有上下文菜单 ;)
    • 啊,谢谢。我很快就创建了那个例子,所以我匆忙错过了(我使用不同的类和正确的 WM_RBUTTONUP 进行开发)。我已经进行了进一步的测试并发现了问题所在 - 我使用带有手写笔的计算机进行开发,我认为系统只是将手写笔输入转换为鼠标消息,仅此而已(对于不知道手写笔的应用程序)。因此它可以与标准 Win32 应用程序正常工作(手写笔右键单击什么都不做),但 WPF 应用程序仍然能够检测到该点击,因为它们是手写笔感知的(不知道这一点)。所以现在我需要像低级手写笔钩子这样的东西。
    • 不幸的是,我从未使用过手写笔,也没有触摸屏来测试 WPF 手写笔的行为。但我可以告诉你,它的工作原理非常有趣! HwndStylusInputProvider 仅处理 WM_TABLET_FLICK 和 WM_TABLET_QUERYSYSTEMGESTURESTATUS 并且不引发任何事件。还有一个名为 PenThreadWorker 的类。它启动了一个名为“Stylus Input”的新线程。该线程使用来自名为“penimc.dll”的本机 DLL 中的 GetPenEvent 和 GetPenEventMultiple 函数查询输入事件。然后它触发与互操作结果相对应的 Stylus 事件。
    【解决方案2】:

    即使您尝试设置过滤器,.NET Framework 也可能有一些未记录的 API 将 WPF 的过滤器置于高优先级,根本不允许您的过滤器执行以确保 WPF 正常工作。

    WPF 窗口与普通窗口相同,它们应该与预先存在的输入 API 以及新的 API 一起正常工作,以使 WPF 与远程桌面和其他此类软件一起工作。

    更新:

    Windows Hook 是在早期的 Windows API 中提供的,因为那时还没有事件冒泡和事件预览等概念,而对于此类实现,挂钩很有用。 WPF 已经提供了带有预览事件和事件冒泡的事件过滤,这就是可能不支持挂钩的原因。

    钩子不是 API 的标准部分,因为只有很少的应用程序使用它们。也许您可以在 Microsoft 发布错误,即他们的过滤器不允许您的钩子过滤器。

    【讨论】:

    • 如果它应该与预先存在的输入 API 一起正常工作,那么我认为它应该允许我的应用程序使用钩子过滤输入,因为这是标准窗口的预期行为。无论如何,这就是这个问题的意义所在 - 确定 WPF 正在使用什么,当我知道这些信息时,我可以安排我的应用程序正确过滤其他 WPF 应用程序中的输入(使用驱动程序、API 挂钩等)。
    • +1,感谢您提供的信息,但是我的问题仍未得到解答 - 我仍然想知道 WPF 用于输入处理的内容,因为仍然可能有一些解决方法可以让我实现我所需要的.
    猜你喜欢
    • 2014-04-05
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多