键盘挂钩中的ToAscii/ToUnicode会破坏死键

000*_*000 14 windows unicode keyboard-hook diacritics

似乎如果你在全局WH_KEYBOARD_LL钩子中调用ToAscii()或者ToUnicode()同时按下死键,它将被"销毁".

例如,假设您已将Windows中的输入语言配置为西班牙语,并且您希望在程序中键入带重音的字母á.通常情况下,您按下单引号键(死键),然后按字母"a",然后在屏幕上显示重音á,如预期的那样.

但是,如果您调用ToAscii()ToUnicode()使用低级键盘挂钩功能,则此功能无效.看来,死键被破坏,所以没有重音字母á显示了在屏幕上.删除对上述函数的调用可以解决问题...但不幸的是,我需要能够调用这些函数.

我用谷歌搜索了一段时间,虽然很多人似乎都有这个问题,但没有提供好的解决方案.

任何帮助将非常感激!

编辑:我正在调用ToAscii()将我的LowLevelKeyboardProc钩子函数中收到的虚拟键代码和扫描代码转换为将在屏幕上显示给用户的结果字符.

我尝试过MapVirtualKey(kbHookData->vkCode, 2),但这并不像"完整"那样功能ToAscii(); 例如,如果你按Shift + 2,你将得到'2',而不是'@'(或者Shift + 2将为用户的键盘布局/语言产生).

ToAscii() 是完美的...直到按下死键.

EDIT2:这是钩子函数,删除了无关信息:

LRESULT CALLBACK keyboard_LL_hook_func(int code, WPARAM wParam, LPARAM lParam) {

    LPKBDLLHOOKSTRUCT kbHookData = (LPKBDLLHOOKSTRUCT)lParam;
    BYTE keyboard_state[256];

    if (code < 0) {
        return CallNextHookEx(keyHook, code, wParam, lParam);
    }

    WORD wCharacter = 0;

    GetKeyboardState(&keyboard_state);
    int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
                     keyboard_state, &wCharacter, 0);

    /* If ta == -1, a dead-key was pressed. The dead-key will be "destroyed"
     * and you'll no longer be able to create any accented characters. Remove
     * the call to ToAscii() above, and you can then create accented characters. */

    return CallNextHookEx(keyHook, code, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)

Kri*_*jic 5

很旧的一个线程。不幸的是,它不包含我正在寻找的答案,而且似乎没有一个答案能正常工作。我终于通过检查解决了这个问题MSB的的MapVirtualKey功能,调用前ToUnicode/ ToAscii。似乎很有魅力:

if(!(MapVirtualKey(kbHookData->vkCode, MAPVK_VK_TO_CHAR)>>(sizeof(UINT)*8-1) & 1)) {
    ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
        keyboard_state, &wCharacter, 0);
}
Run Code Online (Sandbox Code Playgroud)

引用 MSDN 上的返回值MapVirtualKey,如果 MAPVK_VK_TO_CHAR使用:

[...] 死键(变音符号)通过设置返回值的最高位来表示。[...]


sor*_*rin 3

  1. 停止使用 ToAscii() 并使用 ToUncode()
  2. 请记住,ToUnicode 可能不会在死键上返回任何内容 - 这就是它们被称为死键的原因。
  3. 任何键都将具有扫描码或虚拟键码,但不一定是字符。

您不应该将按钮与字符组合起来 - 假设任何键/按钮都具有文本表示形式 (Unicode) 是错误的。

所以:

  • 对于输入文本,请使用Windows 报告的字符
  • 要检查按下的按钮(例如游戏),请使用扫描码虚拟键(可能虚拟键更好)。
  • 对于键盘快捷键,请使用虚拟键代码。