看来,如果您在全局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);
}

最佳答案

相当老的线程。不幸的是,它没有包含我正在寻找的答案,而且似乎都无法正常工作。我终于通过在调用MapVirtualKey/ToUnicode之前检查ToAscii函数的MSB来解决了这个问题。似乎在工作就像一种魅力:

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

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

10-07 16:09