ToUnicode没有返回正确的字符 [英] ToUnicode doesn't return correct characters

查看:79
本文介绍了ToUnicode没有返回正确的字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在低级键盘挂钩中调用ToUnicode并打印它返回的字符.但是,该函数似乎没有考虑是否按下了特殊键(例如Shift或Caps Lock),因此输出与MapVirtualKey函数相同,并且当前键的虚拟代码作为参数传递.

I tried to call the ToUnicode inside a low level keyboard hook and print the character(s) it returned. However, it seems that the function doesn't take into account whether special keys, such as shift or caps lock were pressed, so the output is the same as from MapVirtualKey function with current key's virtual code passed as parameter.

例如(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)

我如何调用函数(在挂钩过程中):

How I call the function (inside the hook procedure):

    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_RETURNVK_SHIFT)的GetKeyState会导致它返回正确的字符,例如:

Later I noticed that calling GetKeyState with any virtual key code passed as parameter (e.g. VK_RETURN, VK_SHIFT) before ToUnicode causes it to return the correct character, e.g.:

abcd => abcd (correct)
[caps lock]abcd => ABCD (correct)
ab[holding shift]cd => abCD (correct)

它还可以正确返回与键盘区域设置相关的键,然后再按AltGr,例如[AltGr]a => ą.

It also returns properly keyboard locale dependent keys pressed with AltGr then, e.g. [AltGr]a => ą.

上面的示例并不完全正确,因为出现了另一个问题-例如按下了大写锁定,下一个字符仍然取决于其前一个状态,只有后一个字符会受到影响,例如:

The above example isn't entirely correct, since there appears another problem - if e.g. caps lock was pressed, the next character still depends on its previous state, only the latter characters are affected, e.g.:

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>)解决了其中一个问题吗?后一个大写锁定(和其他特殊键)问题的原因是什么?

Have you any idea why the GetKeyState(<whatever>) fixes one of the problems and what's the cause of the latter caps lock (and other special keys) problem?

推荐答案

部分答案:

Windows文档建议GetKeyboardStateGetKeyState对于对应的键返回相似的结果,当在Windows消息循环中正确使用键盘消息的Windows消息循环中使用这些功能时,情况就是这样.

Windows documentation suggests GetKeyboardState and GetKeyState return similar result for the correspond keys, and this is true when these functions are used in a Windows message loop, where keyboard messages are properly translated.

但是,在这种情况下,我们具有挂钩功能,GetKeyboardState无法正确填充键盘.首先调用GetKeyState,将更改键盘状态,随后对GetKeyboardState的调用将按预期进行.我不知道为什么!

In this case however, we have a hook function, GetKeyboardState doesn't properly fill the keyboard. Calling GetKeyState first, will change the keyboard state, the subsequent call to GetKeyboardState will work as expected. I don't know why!

其他奇数,GetKeyState返回SHORT值,而GetKeyboardState填充BYTE数组.但这没有什么区别,因为我们只对高位和低位感兴趣.

Other oddities, GetKeyState returns SHORT value, while GetKeyboardState fills BYTE array. But this shouldn't make a difference since we are only interested in high and low bits.

HHOOK hook;
LRESULT CALLBACK hook_procedure(int code, WPARAM wparam, LPARAM lparam)
{
    if(code == HC_ACTION)
    {
        if(wparam == WM_KEYDOWN)
        {
            KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT*)lparam;
            BYTE state[256] = { 0 };
            wchar_t str[10] = { 0 };
            GetKeyState(VK_SHIFT);
            GetKeyState(VK_MENU);
            GetKeyboardState(state);
            if (ToUnicode(kb->vkCode, kb->scanCode, 
                state, str, sizeof(str)/sizeof(*str) - 1, 0) > 0)
            {
                if(kb->vkCode == VK_RETURN) std::wcout << "\r\n";
                else std::wcout << str;
            }
        }
    }
    return CallNextHookEx(hook, code, wparam, lparam);
}

这篇关于ToUnicode没有返回正确的字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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