有没有一种方法可以以编程方式找出计算机的键盘类型(即按键的位置,以及哪些位置存在哪些额外的按键)?
如果键盘非常不标准,那么一点点错误是可以接受的,但总的来说,重点是构建一个类似屏幕键盘的应用程序,可以在屏幕上动态绘制键盘布局,并且精度很高。
当连接到计算机时,键盘会向操作系统发送“扫描码”。在 Windows 上,扫描代码随后会转换为虚拟键(与硬件无关的键盘映射),然后转换为真实字符。
MapVirtualKeyEx()
功能允许您在扫描码、虚拟按键和字符之间进行转换。它还应该能够告诉您密钥是否不存在。
GetKeyboardLayout()
一起告诉您哪个键盘在任何时间点处于活动状态(不同运行的应用程序的键盘布局可能不同),它应该允许您构建相当准确的键盘映射。
keyboard input section of the MSDN
我要补充一点,所有键盘的布局几乎相同。虽然无法知道按键的物理位置,但您可以通过扫描代码和您自己的键盘的基本知识来猜测。
键盘没有任何机制可以告诉 Windows 其物理布局是什么样的。使用 Windows 版本的屏幕键盘 osk.exe 可以轻松查看。它似乎能够猜测机器的外形(笔记本电脑与台式机),但在我的笔记本电脑上,它与键盘的布局不匹配。
使用 osk.exe 布局作为模板,这样就没有人会抱怨你的布局不匹配。
2023 年更新
Windows 10 中添加了一个新的 KEYBOARD_EXTENDED_ATTRIBUTES 结构体和 IOCTL_KEYBOARD_QUERY_EXTENDED_ATTRIBUTES IOCTL,可以返回其他键盘信息。
请参阅最新 HID 使用表规范中的“15.18 描述性控件”。这些来自 2013 年采用的HID 使用表审查请求 42:消费者页面键盘辅助控件。
bool QueryInfo(const ScopedHandle& interfaceHandle)
{
// https://docs.microsoft.com/windows/win32/api/ntddkbd/ns-ntddkbd-keyboard_extended_attributes
KEYBOARD_EXTENDED_ATTRIBUTES extended_attributes{ KEYBOARD_EXTENDED_ATTRIBUTES_STRUCT_VERSION_1 };
DWORD len = 0;
if (!DeviceIoControl(interfaceHandle.get(), IOCTL_KEYBOARD_QUERY_EXTENDED_ATTRIBUTES, nullptr, 0, &extended_attributes, sizeof(extended_attributes), &len, nullptr))
return false;
DCHECK_EQ(len, sizeof(extended_attributes));
FormFactor = extended_attributes.FormFactor;
KeyType = extended_attributes.IETFLanguageTagIndex;
PhysicalLayout = extended_attributes.PhysicalLayout;
VendorSpecificPhysicalLayout = extended_attributes.VendorSpecificPhysicalLayout;
IETFLanguageTagIndex = extended_attributes.IETFLanguageTagIndex;
ImplementedInputAssistControls = extended_attributes.ImplementedInputAssistControls;
return true;
}
但似乎这些并没有被供应商采用,我的现代 Logitech MX 键键盘在这些字段中返回零值..