WPF用什么来捕获鼠标和键盘输入?

时间:2011-02-17 23:47:32

标签: .net wpf input hook mouse-hook

我在全球范围内(系统范围内)使用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
    包含带有默认上下文菜单的TextBox,您可以在其中测试鼠标右键。当HookTester运行时,您不能使用鼠标右键调用上下文菜单。

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

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

下载SO5036143.ZIP: mirror 1mirror 2

2 个答案:

答案 0 :(得分:11)

  • WPF窗口创建HwndSource (Window.CreateSourceWindow)。
  • HwndSource创建HwndWrapper (HwndSource.Initialize)。
  • HwndWrapper用窗口创建Win32窗口 委派Windows的程序 消息到钩子,由。指定 HwndSource。
  • 一个钩子是 HwndSource.InputFilterMessage那个 将Windows消息委派给四个 输入提供者:手写笔,鼠标, 键盘,appcommand。
  • 提供商解析 适当的Windows消息和 调用InputManager来引发输入 元素上的事件。

HwndMouseInputProvider处理消息,例如WM_MOUSEMOVE,WM_LBUTTONDOWN等。所以我认为没有用于处理鼠标和键盘输入的DirectInput。

答案 1 :(得分:1)

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

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

<强>更新

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

Hooks不是API的标准组成部分,因为只有极少数应用程序使用它们。也许你可以在微软发布他们的过滤器不允许你的钩子过滤器的bug。