我试图在低级键盘钩子里调用 ToUnicode
并打印它返回的字符 . 但是,似乎该功能没有考虑是否按下了特殊键,例如shift或大写锁定,因此输出与 MapVirtualKey
函数相同,当前键的虚拟代码作为参数传递 .
例如( pressed keys => characters returned by ToUnicode
):
abcd => abcd (correct)
[caps lock]abcd => abcd (wrong: should be ABCD)
ab[holding shift]cd => abcd (wrong: should be abCD)
我如何调用该函数(在钩子程序内):
KBDLLHOOKSTRUCT* pressedKeyInformation = (KBDLLHOOKSTRUCT*)lParam;
BYTE keysStates[256]; // 256 bo tyle virtualnych klawiszy wpisze GetKeyboardState
if(!GetKeyboardState(keysStates))
//error
else
{
WCHAR charactersPressed[8] = {};
int charactersCopiedAmount = ToUnicode(pressedKeyInformation->vkCode, pressedKeyInformation->scanCode, keysStates, charactersPressed, 8, 0);
//std::wcout << ...
}
后来我发现在 ToUnicode
之前调用 GetKeyState
作为参数传递的任何虚拟键码(例如 VK_RETURN
, VK_SHIFT
)会导致它返回正确的字符,例如:
abcd => abcd (correct)
[caps lock]abcd => ABCD (correct)
ab[holding shift]cd => abCD (correct)
它还返回正确的键盘区域设置依赖键,用AltGr按下,例如, [AltGr]a => ą
.
上面的例子并不完全正确,因为出现了另一个问题 - 例如,按下大写锁定,下一个字符仍取决于其先前的状态,只有后一个字符受到影响,例如:
abcd => abcd (correct)
(caps lock is off)[caps lock]abcd => aBCD (wrong: should be ABCD)
(caps lock is off)ab[caps lock]cd => abcD (wrong: should be abCD)
您是否知道为什么 GetKeyState(<whatever>)
修复了其中一个问题以及后者大写锁定(以及其他特殊键)问题的原因是什么?
1 回答
部分答案:
Windows文档建议
GetKeyboardState
和GetKeyState
返回相应键的类似结果,当在Windows消息循环中使用这些函数时,这是正确的,其中键盘消息被正确转换 .但是在这种情况下,我们有一个钩子函数,
GetKeyboardState
没有正确填充键盘 . 首先调用GetKeyState
将改变键盘状态,随后对GetKeyboardState
的调用将按预期工作 . 我不知道为什么!其他奇怪的事情,
GetKeyState
返回SHORT
值,而GetKeyboardState
填充BYTE
数组 . 但这不应该有所作为,因为我们只对高位和低位感兴趣 .