65.9K
CodeProject 正在变化。 阅读更多。
Home

在 32/64 位环境下加载键盘布局 (KbdLayerDescriptor)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (12投票s)

2012年8月13日

Ms-PL

3分钟阅读

viewsIcon

48702

downloadIcon

2378

当在一个 64 位系统上以 32 位应用程序加载键盘 DLL 时,键盘 DLL 文件无法按预期工作,此类可以解决此问题。

引言

Windows 使用 kbd**.dll 文件加载键盘。当在 64 位系统上的 32 位应用程序中加载键盘时,会得到一个损坏的数组。

这个小小的技巧可以处理在 64 位系统上运行的 32 位应用程序的键盘 DLL 加载。

背景  

这个问题是在我创建一个想要支持多语言的屏幕键盘时发现的。

在搜索了几个论坛后,我没有找到任何好的解决方案。DLL 导入在两个系统上是相同的,但在运行 `KbdLayerDescriptor()` 初始化后,数组实际上是损坏的。一个名为 `pVkToWcharTable` 的元素始终为 `NULL`。这个数组显示了虚拟键 (VK) 和字符之间的关联,这对于显示键盘至关重要。

在 Microsoft DDK 的 `kbd.h` 头文件中,这个指针被定义为:

#if defined(BUILD_WOW6432)
    #define KBD_LONG_POINTER __ptr64
#else
     #define KBD_LONG_POINTER
#endif

这在 32 位系统上运行的 32 位应用程序上效果很好,但在 64 位系统上则不然。

如果您定义 `BUILD_WOW6432` 并将应用程序编译为 64 位,程序将按预期工作。

是什么导致了这种奇怪的行为?在对该主题进行了一些研究后,我在 MSDN 上找到了 可能的原因。一个定义为 `__ptr32` 的指针在 64 位系统上会被强制转换。如果 `KbdLayerDescriptor()` 实际上使用了 `sizeof()` 和其他函数来获取长度,它可能会超出数组的范围。

我的解决方案是使用此定义创建“我自己的” 64 位变量:

#define KBD_LONG_POINTER64 __ptr64

查看 kbd64.h 文件,了解围绕此 64 位定义重命名的所有变量/函数。`kbd64.h` 只是一个重命名的 `kbd.h`,以确保自定义 64 位指针的定义。Kbd64.h 只是一个重命名的 kbd.h,以确保自定义 64 位指针的定义。

演示

包含的演示显示了如何正确初始化 DLL 和填充数组。它没有显示如何处理修饰键和死键,这不是主题的关键部分。

如果您正在研究如何处理死键或对这些“奇怪”的 kbd**.dll 文件有任何疑问,请查看 Michael Kaplan 的 Sorting it all Out 并搜索 KbdLayerDescriptor。

使用代码

CKLL 类有四个公共函数 + 一个辅助函数(来自 KLL.h)。

//Loads the DLL into the handler
BOOL	LoadDLL(CString sKeyboardDll);
	
//Get the counts of virtual keys (VK)
USHORT	GetVKCount();
 
//Get the char(s) linked to that VK
CString	GetChar(USHORT iVK);
 
//Get the scan code(s) linked to that VK
CString GetSC(USHORT iVK);
 
//Helper: Return TRUE if 64-bit, false if 32-bit
BOOL	Is64BitWindows();

如果您已经根据 Microsoft 的 `kbd.h` 头文件编写了自己的函数,那么您可以使用 kbd64.h 头文件,替换变量并将 64 添加到末尾;例如 PKBDTABLES -> PKBDTABLES64。然后,您可以使用 `Is64BitWindows()` 来检查应用程序正在运行的系统类型。

查看 `CKLL` 类中的 `Fill32()` 和 `Fill64()` 函数,以了解其工作原理。

关注点

键盘 DLL 是使用 Microsoft Keyboard Layout Creator 创建的,通过使用内置函数,您可以轻松地创建自定义 DLL,而无需任何麻烦。

扫描码 (SC) 与物理布局之间的关系非常有趣。

来源 - 将上图中的扫描码值与 `KeyboardLayout` 的结果进行比较。

有了这些知识,创建屏幕键盘并呈现您以前从未使用过的键盘语言就会容易得多。

QWERTY 范围似乎每次都能匹配,您还可以将其与 Microsoft 自己的 键盘布局 进行匹配,以确保其正确性。

反馈

如果您以不同的方式解决了这个问题,我希望在评论区听到您的反馈!

历史

v1.0 发布给公众。

© . All rights reserved.