Странный скан-код 02 2A (554) в SendInput LShift - PullRequest
0 голосов
/ 11 апреля 2020

Я написал программу для использования внешнего (беспроводного) цифрового планшета в качестве устройства ввода для игр. Я использую NUMPAD0, NUMPAD. и ENTER для клавиш-модификаторов shift, ctrl и alt соответственно, и я сопоставил остальные клавиши цифровой клавиатуры с WASD и некоторыми другими ключами. Я настроил LowLevelKeyboardPro c для перехвата и приема "реального" ввода с цифровой клавиатуры и отправки пользовательского WM_MESSAGE на Windows Сообщение l oop моего приложения, чтобы затем отправлять сопоставленный "новый" ввод через SendInput (используя коды сканирования ключей, которые я хочу смоделировать).

Это все работает нормально и как и ожидалось. За исключением левой клавиши Shift: всякий раз, когда я нажимаю NUMPAD0, который отображается на левую клавишу Shift, отправляется не только правильный код сканирования 0x2A = 42, но и другая кнопка с кодом сканирования 0x022a = 554. Это выглядит как своего рода флага в бите № 9, так как 554 равен 42 + 2 ^ 9, но я могу найти любую документацию по этому вопросу. Я читал о расширенных 2-байтовых кодах сканирования с префиксом 0xE0, но не 0x02, как в этом случае , Это также происходит только с симулированной клавишей Shift; Ctrl и Alt ведет себя просто отлично. Соответствующие части как клавиатуры, так и сообщений windows:

LowLevelKeyboardPro c:

LPWSTR convertToHex(LPBYTE in, size_t size_in_Bytes)
{
    std::stringstream tempS;
    tempS << std::hex;
    for(int i = 0; i<size_in_Bytes; i++)
    {
        tempS << std::setfill('0') << std::setw(2) << int(in[i]) << " ";
    }
    std::string tempString = tempS.str();
    std::wstring tempW(tempString.begin(), tempString.end());

    LPWSTR out= (LPWSTR) malloc((tempW.size()+2)* sizeof(WCHAR));
    StringCbCopyW(out, tempW.size()* sizeof(WCHAR), tempW.c_str());
    return out;
}

LRESULT CALLBACK LowLevelKeyboardProc(__in  int nCode, __in  WPARAM wParam, __in  LPARAM lParam)
{
    KBDLLHOOKSTRUCT *key=(KBDLLHOOKSTRUCT *)lParam;
    wchar_t tempString[128];

    LPWSTR hexOut = convertToHex((LPBYTE) key , sizeof(KBDLLHOOKSTRUCT));
    StringCbPrintfW(tempString, sizeof(tempString), L"HEX: %s \n", hexOut);
    OutputDebugStringW(tempString);
    free(hexOut);

    //if(key->scanCode > 0xFF)
    //  return -1; //ignore strange scancode
    if(nCode==HC_ACTION)
    {
        if(isNumpad)
        {
            auto it = KeyMap.find(key->scanCode);
            if(it != KeyMap.end())
            {
                PostMessage(hwndMain, WM_MY_KEYDOWN, (key->flags & 128), it->first);
                StringCbPrintfW(tempString, sizeof(tempString), L"Intercept Key, VK: %d, scan: %d, flags: %d, time: %d, event: %d \n", key->vkCode, key->scanCode, key->flags, key->time, wParam);
                OutputDebugStringW(tempString);
                return -1;
            } 
        }
    }
    // delete injected flag
    //UINT mask = (1<<4);
    //if(key->flags & mask)
    //  key->flags ^= mask;
    //key->scanCode = MapVirtualKey(key->vkCode, MAPVK_VK_TO_VSC);
    StringCbPrintfW(tempString, sizeof(tempString), L"Output key: VK: %d, scan: %d, flags: %d, time: %d, event: %d \n", key->vkCode, key->scanCode, key->flags, key->time, wParam);
    OutputDebugStringW(tempString);
    return CallNextHookEx(hhkHook,nCode,wParam,lParam);
}

Windows Сообщение:

case WM_MY_KEYDOWN:
{
    DWORD OLD_KEY = lParam;
    DWORD NEW_KEY = KeyMap[OLD_KEY];
    bool keyUP = wParam;

    INPUT inputdata;
    inputdata.type=INPUT_KEYBOARD;
    inputdata.ki.dwFlags=KEYEVENTF_SCANCODE ;
    inputdata.ki.wScan=NEW_KEY;
    inputdata.ki.wVk=MapVirtualKey(NEW_KEY, MAPVK_VSC_TO_VK);
    inputdata.ki.time = 0;//key->time;
    inputdata.ki.dwExtraInfo = 0;//key->dwExtraInfo;

    if(keyUP)
    {
        inputdata.ki.dwFlags |= KEYEVENTF_KEYUP;
    }
    Sleep(1);
    bool sendKey=false;
    switch(inputdata.ki.wScan)
    {
        //there once was some additional logic here to handle the modifier keys ctrl, alt and shift seperately, but not anymore

        default:
        {
            sendKey=true;
        }
        break;
    }
    if (sendKey)
    {
        UINT result = SendInput(1, &inputdata, sizeof(INPUT));
        if(!result) 
            ErrorExit(L"SendInput didn't work!");
    }

}
break;

Вывод при нажатии клавиши обычного переключения на физической клавиатуре:

//key down
HEX: a0 00 00 00 2a 00 00 00 00 00 00 00 29 cf d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 42, flags: 0, time: 13815593, event: 256 
//key up
HEX: a0 00 00 00 2a 00 00 00 80 00 00 00 e5 cf d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 42, flags: 128, time: 13815781, event: 257 

Вывод при нажатии клавиши имитации переключения на цифровой клавиатуре:

//keydown event numpad
HEX: 60 00 00 00 52 00 00 00 00 00 00 00 a1 ea d2 00 00 00 00 00 00 00 00 00  
Intercept Key, VK: 96, scan: 82, flags: 0, time: 13822625, event: 256 
//keydown event simulated shift key
HEX: a0 00 00 00 2a 00 00 00 10 00 00 00 a1 ea d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 42, flags: 0, time: 13822625, event: 256 
// key up event with strange scancode 554 <- THIS IS WHAT I AM TALKING ABOUT!
HEX: a0 00 00 00 2a 02 00 00 80 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 554, flags: 128, time: 13822781, event: 257 
// key up event numpad
HEX: 2d 00 00 00 52 00 00 00 80 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00  
Intercept Key, VK: 45, scan: 82, flags: 128, time: 13822781, event: 257 
// key down with strange scan code
HEX: a0 00 00 00 2a 02 00 00 00 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 554, flags: 0, time: 13822781, event: 256 
//key up event simulated shift key
HEX: a0 00 00 00 2a 00 00 00 90 00 00 00 3d eb d2 00 00 00 00 00 00 00 00 00  
Output key: VK: 160, scan: 42, flags: 128, time: 13822781, event: 257 

Еще одна вещь, на которую следует обратить внимание: событие key-up этого странного кода сканирования ключа 554 также точно противоположно тому, что есть остальные (см. вывод). Поскольку я могу просто съесть событие ключа для этого странного кода сканирования 554, это на самом деле не так много проблемы с точки зрения функциональности, но я все же хотел бы знать, что представляет собой этот код сканирования 554.

...