键盘挂钩中的ToAscii/ToUnicode会破坏死键 [英] ToAscii/ToUnicode in a keyboard hook destroys dead keys
问题描述
如果在全局WH_KEYBOARD_LL挂钩中调用ToAscii()
或ToUnicode()
,并且按下了死键,它将被破坏".
It seems that if you call ToAscii()
or ToUnicode()
while in a global WH_KEYBOARD_LL hook, and a dead-key is pressed, it will be 'destroyed'.
例如,假设您已经在Windows中将输入语言配置为西班牙语,并且想要在程序中键入带重音的字母á.通常,您将按单引号键(无用键),然后按字母"a",然后在屏幕上按预期显示带重音符号的á.
For example, say you've configured your input language in Windows as Spanish, and you want to type an accented letter á in a program. Normally, you'd press the single-quote key (the dead key), then the letter "a", and then on the screen an accented á would be displayed, as expected.
但是,如果您在低级键盘挂钩函数中调用ToAscii()
或ToUnicode()
,则此操作将无效.似乎该死键已被破坏,因此屏幕上没有出现带重音的字母á.删除对上述函数的调用可以解决此问题……但是,不幸的是,我需要能够调用这些函数.
But this doesn't work if you call ToAscii()
or ToUnicode()
in a low-level keyboard hook function. It seems that the dead key is destroyed, and so no accented letter á shows up on screen. Removing a call to the above functions resolves the issue... but unfortunately, I need to be able to call those functions.
我搜索了一段时间,虽然很多人似乎都遇到了这个问题,但没有提供好的解决方案.
I Googled for a while, and while a lot of people seemed to have this issue, no good solution was provided.
任何帮助将不胜感激!
I'm calling ToAscii()
to convert the virtual-key code and scan code received in my LowLevelKeyboardProc hook function into the resulting character that will be displayed on screen for the user.
我尝试了MapVirtualKey(kbHookData->vkCode, 2)
,但这还不能像ToAscii()
那样完成"一个功能.例如,如果您按Shift + 2,您将得到"2",而不是"@"(或将为用户的键盘布局/语言产生的Shift + 2).
I tried MapVirtualKey(kbHookData->vkCode, 2)
, but this isn't as "complete" a function as ToAscii()
; for example, if you press Shift + 2, you'll get '2', not '@' (or whatever Shift + 2 will produce for the user's keyboard layout/language).
ToAscii()
很完美...直到按下死键为止.
ToAscii()
is perfect... until a dead-key is pressed.
这是挂钩函数,其中删除了不相关的信息:
Here's the hook function, with irrelevant info removed:
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);
}
推荐答案
相当老的线程.不幸的是,它没有包含我正在寻找的答案,而且所有答案似乎都无法正常工作.我终于通过检查MSB 来解决了该问题. MapVirtualKey
函数,然后调用ToUnicode
/ToAscii
.似乎像一种魅力一样工作:
Quite an old thread. Unfortunately it didn't contain the answer I was looking for and none of the answers seemed to work properly. I finally solved the problem by checking the MSB of the MapVirtualKey
function, before calling ToUnicode
/ ToAscii
. Seems to be working like a charm:
if(!(MapVirtualKey(kbHookData->vkCode, MAPVK_VK_TO_CHAR)>>(sizeof(UINT)*8-1) & 1)) {
ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
keyboard_state, &wCharacter, 0);
}
如果使用MAPVK_VK_TO_CHAR
,则在返回值MapVirtualKey
上引用MSDN:
Quoting MSDN on the return value of MapVirtualKey
, if MAPVK_VK_TO_CHAR
is used:
[...]死键(变音符号)通过设置返回值的高位来指示. [...]
[...] Dead keys (diacritics) are indicated by setting the top bit of the return value. [...]
这篇关于键盘挂钩中的ToAscii/ToUnicode会破坏死键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!