Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using KBDLLHOOKSTRUCT to determine first key press

I'm using a low-level keyboard hook on windows. It works like a charme, despite of the fact that I'm currently unable to tell whether the key was initially pressed or pressed again. The documentation (+here) says, that bit 7 holds the transition state. But this seems only to be true when the key is being released. Bit 7 is sadly not set when I firstly press the key.

Is there any way to tell whether the key is pressed initially?

like image 714
The Wavelength Avatar asked Nov 11 '22 02:11

The Wavelength


1 Answers

I happen to run into this problem recently. I can't find any good solutions, but I ended up using a flag and a GetAsyncKeyState before SetWindowHookEx.

BOOL wasDown;

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        LPKBDLLHOOKSTRUCT key = (LPKBDLLHOOKSTRUCT) lParam;
        if (key->vkCode == VK_SOMETHING) {
            switch (wParam) {
                case WM_KEYDOWN:
                case WM_SYSKEYDOWN:
                    if (!wasDown) {
                        // Processing on first key down
                        wasDown = true;
                    }
                    break;
                case WM_KEYUP:
                case WM_SYSKEYUP:
                    // Processing on key up
                    wasDown = FALSE;
                    break;
            }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

wasDown = GetAsyncKeyState(VK_SOMETHING) < 0;
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);

Of course, this code only does it for one key. You can use an array of flags to do multiple keys. Depending on your application you could also unconditionally set the flag to false if you want the first press after your hook is set.

like image 141
quantum Avatar answered Nov 15 '22 10:11

quantum