1

我想在键盘上触发 Keypress。在物理键盘上 - 因此它必须以该特定键盘作为其源来遍历所有内核过滤器。这样的事情可能吗?

我查看了 DeviceIOCtrl 和 IOCTL_KEYBOARD_INSERT_DATA,但没有找到文档。有人说,它没有在驱动程序中实现。另一个来源尝试使用 IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER,但也说,它可能不适用于那种东西

在键盘通过内核过滤器之前,是否有其他选项可以触发键盘上的按键?

为什么我什至想这样做? 是的,这可能是一个 XY 问题,但它是我目前能想到的唯一解决方案。我只想截取来自特定键盘的键。有 RawInput,它告诉我击键的键盘,但无法拦截,还有一个 LowLevel Keyboard 钩子可以拦截,但无法识别键盘。更糟糕的是,RawInput在 LowLevel-Hook之后触发,因此在截取击键之前无法获取键盘。有一些神奇的独角兽方式可以使用在 RawInput 之后触发的全局 Hook,但处理所有边缘情况看起来很痛苦。

有一个API可以拦截我选择的键盘敲击。它基本上安装了一个允许拦截击键获取键盘ID。但是:该 ID 有点随意,并且不遵循我可以用来将整数值与特定键盘设备相关联的任何规则。例如,重新插入设备时它会发生变化,与 \Device\KeyboardClassX 等无关。因此,每次重新连接键盘/启动应用程序时,用户都必须主动按下一个键,以便我可以确定哪个物理键盘的 id实际上代表。我想避免这种情况并自动获取特定设备的 ID。我的想法是触发键盘(-控制器?)中的按键并使用驱动程序捕获它,从而将任意 ID 与设备相关联。

因此,如果我的 Y 有不同的 X,请随时提出建议。我想避免所有那些RawInput 和 GlobalHook 的 Magic Unicorn Way不能可靠工作的边缘情况。任何主要语言的示例都可以。也许没有办法解决在应用程序启动时手动按下按钮来识别键盘的 UX 不便......

4

1 回答 1

0

我想我找到了适合我的解决方案/黑客。我正在避开问题中描述的神奇独角兽,并坚持我已经拥有的驱动程序。

当我意识到我已经能够将键盘敲击注入 Kernel-Land 时,第一个想法就出现了。只是不是特定的键盘,而是随机的键盘。我最初计划使用 RawInput 查询所有可用的 HID 键盘,然后将这些项目中的每一个与驱动程序中的 ID 相关联。但为什么不反过来呢?通过击键注入一个随机的设备 ID,等待 RawInput 触发相应的键盘。

所以这就是我所做的。我告诉驱动程序为特定设备注入按键并等待按键到达 RawInput。只会出现两个问题:

  1. 某些击键无法通过键盘手柄到达 RawInput-API。所以我将无法关联这些
  2. 一旦他们越过司机,我就不能再拦截他们了。(不能使用 LowLevelHooks,因为它们在 RawInput 之前运行,不想使用 Global Hooks,因为它们有很多缺点)

所以我只需要找到一个根本不做任何事情的钥匙。幸运的是,驱动程序使用扫描码。这份文件告诉我,有一系列扫描码(0x55 - 0x7f)可供免费获取,每个制造商都在里面做了一些定制的事情。所以这就是我开始扫描并在 RawInput-API 中查找结果的地方,方法是盲目地将这些 ScanCode 触发到驱动程序中。

免责声明:如果你想这样做,你最好至少有两个屏幕,并确保你的焦点窗口不在 VisualStudio 的顶部,因为你的焦点窗口会立即全屏,只要窗口被聚焦,你的键盘就会停止工作...即使您重新获得键盘控制权,您也无法退出全屏模式...

事实上,似乎有相当多的免费扫描码可供选择。但其中一些在不同的国家使用或不会在所有键盘驱动程序上触发。我选择了 ScanCode 0x7e,它转换为 KeyCode 194,似乎没有用于任何语言,但适用于我拥有的所有 (2) 个键盘。

此外,此“键”始终包含正确的键盘句柄,因此不会出现关联内容的问题。因此,作为最终实现,我使用 RawInput-API 获取已连接键盘的数量,并循环遍历所有可能的 ID(0-10/20ish 以防止太多查找/等待),直到找到每个键盘的 ID。而且由于扫描码不用于任何事情,用户不会被突然的大写锁定或任何事情打断。此外,每次重新插入键盘时都需要重做,因为每个插入的设备都会获得一个新的 ID,即使它之前已经有一个。

于 2020-07-15T20:53:35.473 回答