ToUnicode не возвращает правильные символы - PullRequest
0 голосов
/ 10 декабря 2018

Я попытался вызвать ToUnicode внутри низкоуровневой клавиатуры и вывести возвращаемые символы.Однако, похоже, что функция не учитывает, были ли нажаты специальные клавиши, такие как Shift или Caps Lock, поэтому вывод такой же, как и у функции MapVirtualKey с виртуальным кодом текущей клавиши, переданным в качестве параметра.

Например (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)

Как я вызываю функцию (внутри процедуры подключения):

    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 << ...
    }

Позже я заметил, что вызов GetKeyState слюбой код виртуальной клавиши, переданный в качестве параметра (например, VK_RETURN, VK_SHIFT) перед ToUnicode, заставляет его возвращать правильный символ, например:

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

Он также возвращает должным образом зависимые от локали клавиши клавиатуры, нажатые сЗатем AltGr, например, [AltGr]a => ą.

Приведенный выше пример не совсем корректен, поскольку возникает другая проблема - если, например, была нажата кнопка caps lock, следующий символ по-прежнему зависит от своего предыдущего состояния, только последние символызатрагиваются, например:

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>) устраняет одну из проблем и в чем причина последнего caps lock (и других специальных ключей)?я проблема?

1 Ответ

0 голосов
/ 10 декабря 2018

Частичный ответ:

Документация Windows предлагает GetKeyboardState и GetKeyState возвращать аналогичный результат для соответствующих клавиш, и это верно, когда эти функции используются в цикле сообщений Windows, где сообщения клавиатуры правильнопереведено.

В этом случае, однако, у нас есть функция ловушки, GetKeyboardState неправильно заполняет клавиатуру.Сначала вызов GetKeyState изменит состояние клавиатуры, последующий вызов GetKeyboardState будет работать как положено.Я не знаю почему!

Другие странности, GetKeyState возвращает значение SHORT, а GetKeyboardState заполняет BYTE массив.Но это не должно иметь значения, так как нас интересуют только старшие и младшие биты.

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);
}
...