4

我目前正在为 Windows 编写一个键盘驱动程序,它提供了一个额外的修饰符并允许直接键入一些额外的字符。例如实引号(“、”、'、'、...)和一些数学字符(ℕ、ℝ、ℚ、ℤ、√、...)。

现在我想像那样提供箭头键。(alt_gr + e = 上;alt_gr + s = 左;alt_gr + d = 下;alt_gr + f = 右)

所以我的问题是,如果箭头键有 Unicode 控制字符,我可以在我的 aVkToWcharTable 或其他解决方案中使用它。这真的很有帮助。

4

1 回答 1

3

我之前没有任何Windows驱动程序编程的经验,所以如果有人发现有问题,请纠正我。

但是我使用的是 NEO 布局(或者准确地说是 AdNW 变体)并且很好奇,所以我下载了 DDK 以查看我可以从文档中学到什么。我真的没有适合你的解决方案,我想你可能已经知道一些这些东西,但我认为写下我发现的东西可能仍然有一些用处,如果只是为了澄清一点。

概述

据我所知,键盘数据可以来自两条路径。有 PS/2 设备,然后有 USB 键盘。两者采用不同的路径(USB 数据的来源在 HID 基础设施中,PS/2 数据由 I8042prt 驱动程序产生),但最终出现在所谓的“键盘类驱动程序”中。

从那里开始,数据要么传递给 DirectInput,要么传递给 user32 遗留接口。布局在哪里发挥作用并不完全清楚,但我认为它是在键盘类驱动程序之上实现的。

布局

键盘布局基本上看起来是一堆数据结构,符合KBDTABLESkbd.h 中定义的结构。基本上,低级驱动程序会产生一个 ScanCode,并且这些代码的解释是通过这种结构完成的。

第一个重要的是pusVSCtoVK,pVSCtoVK_E0pVSCtoVK_E1,它们将驱动程序的原始扫描码(和扩展扫描码)映射到与硬件无关的虚拟键码。这些密钥代码描述了密钥。字符映射稍后出现。所以左光标键产生VK_LEFT,而 S 键产生VK_S,即使布局稍后将其转换为其他内容。

接下来是pCharModifiers,它指定哪些虚拟键是修饰符以及哪些组合会产生不同的移位状态。

最后pVkToWcharTable,根据 shift 状态,将所有虚拟键映射到 Unicode 字符。这是大多数实际布局所在的位置。死键和连字有一些特殊值,但现在让我们把它放在一边。

应用

现在应用程序最终会得到什么?显然,他们可以从通常的窗口消息中获取虚拟键码和扫描码,例如WM_INPUT, WM_KEYDOWN, ...。他们还可以使用诸如ToUnicodeEx. 虚拟键码和 Unicode 字符由布局提供。

对于普通角色来说,一切都很好。应用程序将接收输入事件,向布局请求一个字符,然后就可以了。但是光标键是不同的,因为从虚拟键到字符的映射既不需要也没有意义。应用程序关心密钥,但不关心字符。因此它将基于虚拟键代码的操作。如果是VK_LEFT,则将光标向左移动。如果是VK_RIGHT,则光标向右移动,依此类推。

这给我们留下了一个两难的境地:如果我们想让 ModX + S 向左移动光标,修饰符感知pVkToWcharTable对我们没有帮助,因为应用程序从不要求输入字符,而是要求输入键。显然 S 与左键不是同一个键。生成控制字符(据我所知不存在)很可能也无济于事,因为应用程序不会要求它并且不会解释它。

因此,如果按下正确的修饰键,您真正想要的是 S 键生成不同的虚拟键代码,但布局的数据结构不允许这样的映射。它毕竟不是执行代码,只是一个数据结构。

小键盘呢?

Numpad 似乎做了需要做的事情。按键的扫描码保持不变,但根据 Numlock 状态,它们会产生不同的虚拟按键码。但是,我认为 windows 在这里做了一些特殊处理。这些键的KBDNUMPAD标志设置在pusVSCtoVK. Windows 似乎会检测到这一点并根据 Numlock 状态交换虚拟键。

我至少找到了一些证据。尝试在 Google 中搜索“xxxNumpadCursor”。它出现了一些看似泄露的 Windows 代码。根据 Shift 和 Numlock,有一个检查KBDNUMPAD和似乎替换虚拟键的代码。我怀疑这可以用于此目的。

甚至可能吗?

那么如果布局不能做到这一点,谁能做到呢?显然是一些产生原始扫描码的低级驱动程序。DDK 中有一个所谓的过滤驱动程序示例,称为“kbfiltr”。基本上,这样的过滤器驱动似乎可以挂接到现有驱动程序之上并重写来自驱动程序的数据,因此如果按下另一个键,应该可以将 S 键的扫描码重写为 Left。

但是请注意,这将是一个驱动程序,而不是一个布局。我不确定这是否是一个实际的解决方案。据我所知,不知道所选布局,因此更改将适用于所有布局。(尽管可以在这里实现整个布局,并用一个键将其关闭。)我也不确定安装这样的驱动程序会有多复杂,以及是否需要签署驱动程序,这将使情况更糟。

我真的没有足够的驱动程序编程经验(也就是说根本没有经验),推荐或反对这种方法。可能值得进行一些试验(我更喜欢这里的虚拟机),但它似乎比当前完成的简单布局替换更具挑战性。Autohotkey 解决方案可能仍然是最好的解决方案(缺点是它不适用于所有应用程序)。

更新

我做了更多的研究。我认为可以使用过滤器驱动程序来做到这一点。此驱动程序基本上位于 HID 基础结构或 I8042prt 驱动程序和键盘类驱动程序之间。然后它可以在数据到达类驱动程序之前修改数据,并在它们到达之前替换/删除/添加关键事件。最后,您必须使用特殊布局(用于附加 unicode 字符)以及驱动程序,可以通过设备管理器为单个键盘安装驱动程序。该解决方案应该适用于所有应用程序。

这里的问题是驱动程序签名。作为内核模式驱动程序,必须对其进行签名才能在 64 位 Vista/Win7 中加载它而不会出现丑陋的黑客攻击。而且签约司机并不便宜,所以你基本上不走运。我认为可以通过编写用户模式驱动程序(不需要签名)来避免这种情况,但问题是,过滤器必须安装在键盘类驱动程序下面。可悲的是,用户模式过滤器驱动程序上面不能有内核模式驱动程序。所以这不是一个选择。

所以我认为你基本上坚持使用 AutoHotkey。除非您愿意并且能够编写内核模式驱动程序并忍受签名问题。

于 2011-03-18T13:11:20.923 回答