为什么 GetKeyState 改变了 ToUnicodeEx 的行为? [英] Why GetKeyState changed the behavior of ToUnicodeEx?

查看:23
本文介绍了为什么 GetKeyState 改变了 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+ASHIFT+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+ASHIFT+2到时,代码的行为直接改变了>

The behavior of the code changed directly when pressing SHIFT+A or SHIFT+2 to

KEY:A
KEY:B
KEY:@

我在 ToUnicodeToAsciiExToAscii 上尝试了这个,它们显示了与上面相同的情况.

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 函数启用了SHIFTCaps 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆