为什么 GetKeyState 改变了 ToUnicodeEx 的行为? [英] Why GetKeyState changed the behavior of ToUnicodeEx?
问题描述
在下面的代码中:-
BYTE ks[256];
auto keyboard_layout = GetKeyboardLayout(0);
GetKeyboardState(ks);
auto w = WCHAR(malloc(1));
ToUnicodeEx(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC), ks, LPWSTR(&w), 1, 0, keyboard_layout);
wcout << "KEY:" << w << endl;
输出只显示小写字母,如:-
The output only shows lowercase letters such as :-
KEY:a
KEY:b
KEY:2
即使按下 SHIFT+A 或 SHIFT+2
但是在下面的代码中添加GetKeyState(VK_SHIFT)
和/或GetKeyState(VK_CAPITAL)
:-
But adding GetKeyState(VK_SHIFT)
and/or GetKeyState(VK_CAPITAL)
in the code below:-
auto shifted = false;
auto caps = false;
if (GetKeyState(VK_SHIFT) < 0)
{
shifted = true;
cout << "Shifted!" << endl;
}
if (GetKeyState(VK_CAPITAL) < 0)
{
shifted = true;
cout << "Caps!" << endl;
}
BYTE ks[256];
auto keyboard_layout = GetKeyboardLayout(0);
GetKeyboardState(ks);
auto w = WCHAR(malloc(1));
ToUnicodeEx(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC), ks, LPWSTR(&w), 1, 0, keyboard_layout);
wcout << "KEY:" << w << endl;
当按下SHIFT+A或SHIFT+2到时,代码的行为直接改变了>
The behavior of the code changed directly when pressing SHIFT+A or SHIFT+2 to
KEY:A
KEY:B
KEY:@
我在 ToUnicode
、ToAsciiEx
和 ToAscii
上尝试了这个,它们显示了与上面相同的情况.
I tried this on ToUnicode
, ToAsciiEx
and ToAscii
and they shows the same situation as above.
我在名为 hook.dll
的单独 DLL 文件中使用了 WH_KEYBOARD
钩子,并与控制台应用程序链接.
I used WH_KEYBOARD
hook in a separate DLL file called hook.dll
and linked with a console application.
所以我的问题是:为什么GetKeyState
函数启用了SHIFT 和Caps Lock 键的检测?此外,
So my question is: why GetKeyState
function enabled the detection of SHIFT and Caps Lock key? In addition,
推荐答案
使用 auto w = WCHAR(malloc(1))
是错误的.malloc()
动态分配一个字节块,而不是字符.WCHAR
大小为 2 个字节,但您只分配了 1 个字节.这无关紧要,因为您无论如何都不使用指针.您正在将指针类型转换为单个 WCHAR
,截断指针值.然后在将 &w
传递给 ToUnicodeEx()
时忽略该值,因为它会覆盖 w
的值.由于您没有调用 free()
来释放它,因此您正在泄漏分配的内存.
Using auto w = WCHAR(malloc(1))
is wrong. malloc()
dynamically allocates a block of bytes, not characters. WCHAR
is 2 bytes in size, but you are allocating only 1 byte. Which doesn't matter since you don't use the pointer anyway. You are type-casting the pointer to a single WCHAR
, truncating the pointer value. And then you are dismissing the value when passing &w
to ToUnicodeEx()
as it will overwrite the value of w
. You are then leaking the allocated memory since you are not calling free()
to deallocate it.
您根本不需要 malloc()
:
WCHAR w;
ToUnicodeEx(..., &w, 1, ...);
wcout << "KEY:" << w << endl;
但是,ToUnicodeEx()
可能会返回 2 个以上的字符,因此您应该分配额外的空间来解决这个问题.只需使用本地固定数组,就像您对 GetKeyboardState()
所做的那样.并注意返回值,它包含重要信息.
However, ToUnicodeEx()
can potentially return more than 2 characters, so you should allocate extra room to account for that. Just use a local fixed array, like you do for GetKeyboardState()
. And do pay attention to the return value, it contains important information.
至于关键状态,由于您正在调用GetKeyboardState()
,因此您不需要使用GetKeyState()
.
As for the key states, since you are calling GetKeyboardState()
, you don't need to use GetKeyState()
.
尝试更像这样的事情:
BYTE ks[256];
auto keyboard_layout = GetKeyboardLayout(0);
GetKeyboardState(ks);
if (ks[VK_SHIFT] & 0x80) wcout << L"Shifted!" << endl;
if (ks[VK_CAPITAL] & 0x80) wcout << L"Caps!" << endl;
WCHAR w[5] = {};
int ret = ToUnicodeEx(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC), ks, w, 4, 0, keyboard_layout);
switch (ret)
{
case -1:
wcout << L"DEAD KEY:" << w << endl;
break;
case 0:
wcout << L"NO TRANSLATION" << endl;
break;
case 1:
wcout << L"KEY:" << w << endl;
break;
case 2:
case 3:
case 4:
w[ret] = 0;
wcout << L"KEYS:" << w << endl;
break;
}
这篇关于为什么 GetKeyState 改变了 ToUnicodeEx 的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!