在下面的代码中: -
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;
输出仅显示小写字母,例如: -
KEY:a
KEY:b
KEY:2
即使按 SHIFT + A 或 SHIFT + 2
但在以下代码中添加GetKeyState(VK_SHIFT)
和/或GetKeyState(VK_CAPITAL)
: -
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 时,代码的行为直接改变为
KEY:A
KEY:B
KEY:@
我在ToUnicode
,ToAsciiEx
和ToAscii
上尝试了此操作,它们显示的情况与上述相同。
我在名为WH_KEYBOARD
的单独DLL文件中使用hook.dll
钩子并与控制台应用程序链接。
所以我的问题是:为什么GetKeyState
函数启用了 SHIFT 和 Caps Lock 键的检测?另外,
答案 0 :(得分:4)
使用auto w = WCHAR(malloc(1))
是错误的。 malloc()
动态分配一个字节块,而不是字符。 WCHAR
的大小为2个字节,但您只分配1个字节。哪个没关系,因为你还是不使用指针。您正在将指针压缩为单个WCHAR
,从而截断指针值。然后,在将&w
传递给ToUnicodeEx()
时,您将忽略该值,因为它会覆盖w
的值。然后,您正在泄漏已分配的内存,因为您没有调用free()
来取消分配它。
您根本不需要malloc()
:
WCHAR w;
ToUnicodeEx(..., &w, 1, ...);
wcout << "KEY:" << w << endl;
但是,ToUnicodeEx()
可能会返回超过2个字符,因此您应该为此分配额外的空间。只需使用本地固定数组,就像使用GetKeyboardState()
一样。并且要注意返回值,它包含重要信息。
至于关键状态,由于您致电GetKeyboardState()
,因此无需使用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;
}