在64位系统上运行32位应用程序时,可能会遇到键盘DLL文件加载的问题。这个问题通常表现为在初始化键盘布局时数组被损坏。本文将介绍如何通过一些简单的修改来解决这个问题。
在开发一个多语言的屏幕键盘时,发现了这个问题。尽管搜索了多个论坛,但并没有找到满意的解决方案。在32位系统上,DLL导入是相同的,但是在64位系统上运行时,使用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上可能的原因。在64位系统上,定义为__ptr32的指针会被强制转换。如果KbdLayerDescriptor()实际上使用sizeof()和其他函数来获取长度,它可能会超出数组的范围。
解决方案是创建“”64位变量,使用这个定义:
#define KBD_LONG_POINTER64 __ptr64
查看kbd64.h文件,了解所有围绕这个64位定义重命名的变量/函数。
kbd64.h只是重命名的kbd.h,以确保自己的64位指针定义。
包含的演示展示了如何正确初始化DLL并填充数组。它没有展示如何处理修饰符和死键,这不是主题的重要部分。
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头文件编写了自己的函数,那么可以替换变量,并在结尾添加64;例如PKBDTABLES -> PKBDTABLES64。然后使用Is64BitWindows()来检查应用程序正在运行的系统类型。
查看CKLL类中的Fill32()和Fill64()函数,了解其工作原理。
键盘DLL是使用Microsoft Keyboard Layout Creator创建的,通过使用内置函数,可以轻松创建自定义DLL,无需任何麻烦。
扫描码(SC)和物理布局之间的连接非常有趣。
- 比较上图中的扫描码值与KeyboardLayout的结果。
有了这些知识,创建一个屏幕键盘并展示从未使用过的键盘语言就变得容易多了。
qwerty范围似乎每次都匹配,也可以将其与Microsoft自己的Keyboard Layouts匹配,以确保它是正确的。