【发布时间】:2018-12-09 22:33:33
【问题描述】:
我尝试在低级键盘钩子中调用ToUnicode 并打印它返回的字符。但是,该函数似乎没有考虑是否按下了特殊键,例如 shift 或 caps lock,因此输出与 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 之前使用任何作为参数传递的虚拟键代码(例如VK_RETURN、VK_SHIFT)调用GetKeyState 会导致它返回正确的字符,例如:
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>) 解决了其中一个问题以及导致后一个大写锁定(和其他特殊键)问题的原因是什么?
【问题讨论】:
-
在调用
GetKeyboardState之前同时调用GetKeyState(VK_SHIFT)和GetKeyState(VK_CAPITAL)。您的MCVE 不清楚。你在回复WM_KEYDOWN吗? -
@Barmak Shemirani 是的,我正在回复
WM_KEYDOWN。我会在我回家后更改代码,所以在几个小时内。 -
@BarmakShemirani 现在可以完美运行,谢谢。但是这些调用实际上做了什么?我相信
GetKeyState(key)在内部更新key的状态,对吗?我在msdn上找不到任何线索。您应该发表您的评论作为答案。
标签: winapi keyboard hook keyboard-hook