C++ – Windows: How to query state of modifier keys within low level keyboard hook

chookkeyboardwindows

For a usb keyboard configuration tool I need to intercept all keyboard input and detect which modifier keys and normal keys are pressed simultaneously. Therefore I use a windows low level hook (WH_KEYBOARD_LL) which works fine except that I´m not able to determine if WIN-Key (VK_LWIN / VK_RWIN) is pressed (control / shift and alt is working).

I made a little commandline tool to show the problem:

#include <Windows.h>
#include <iostream>

using namespace std;

HHOOK hKeyboardHook;


LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
    if (nCode < 0 || nCode != HC_ACTION )
        return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);

    KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;

    if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
    {
        // working
        if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
            cout << "CONTROL" << endl;
        if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
            cout << "SHIFT" << endl;
        if(GetAsyncKeyState(VK_MENU) & 0x8000) // ALT
            cout << "ALT" << endl;

        // VK_xWIN not working at all
        if((GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000))
            cout << "WIN" << endl;

        // working for ALTGR/right-handed ALT
        if((GetAsyncKeyState(VK_LCONTROL) & 0x8000) || (GetAsyncKeyState(VK_RCONTROL) & 0x8000))
            cout << "LRCONTROL" << endl;

        // not working at all
        if((GetAsyncKeyState(VK_LSHIFT) & 0x8000) || (GetAsyncKeyState(VK_RSHIFT) & 0x8000))
            cout << "LRSHIFT" << endl;
        if((GetAsyncKeyState(VK_LMENU) & 0x8000) || (GetAsyncKeyState(VK_RMENU) & 0x8000))
            cout << "LRMENU" << endl;
    }

    //return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);
    return 1;
}



int main(int argc, char* argv[])
{
    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );

    MSG message;
    while (GetMessage(&message,NULL,0,0)) {
        TranslateMessage( &message );
        DispatchMessage( &message );
    }

    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

If I return "1" from LowLevelKeyboardProc every key press is "swallowed" (except for CTRL+ALT+DEL and WIN+L). If I call the next hook at the end of the callback function the behaviour changes (and the keys obviously aren´t swallowed any more). Then if WIN key is pressed together with another key I get the information that WIN key is pressed.

What do I have to do to intercept all keyboard input and detect a WIN-key press (using GetAsyncKeyState)? Or is there another way to get all (inkl. WIN) pressed modifier keys?

Best Answer

The documentation for LowLevelKeyboardProc says the following about the return value:

If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure.

So, return 1 says "I've processes the information, and there is nothing else that should be done with these keys".

I'm not certain how you fix the problem with detection of WIN key on it's own - I suspect the system just simply doesn't forward that has a keyboard event until the second key is pressed.

Related Topic