Search code examples
c++winapikeyboard-hook

Low-level keyboard hook: callback not reached


I'm trying to create a quick piece of code to capture the key sequence sent by one of the "hotkey" buttons on my tablet and reprogram its function. The button sends a LWin+LCtrl+Tab when pressed.

After searching around for a while I decided to try using a WH_KEYBOARD_LL hook, but after a few hours I still can't get the hook to work, let alone the actual functionality.

Currently, I have the following:

// TestHook2.cpp

#include "stdafx.h"

HHOOK hook;
BOOL gotKey;
LRESULT WINAPI KeyTrap(int, WPARAM, LPARAM);
BOOL CtrlHandler(DWORD);

int _tmain(int argc, _TCHAR* argv[])
{
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
    HMODULE currentProcess = GetModuleHandle(NULL);
    hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyTrap, currentProcess, 0);

    if (!hook) {
        printf("No hook, quitting!\n");
        return 1;
    }

    while(1) {
        if(gotKey) printf("Got Key!\n");
        gotKey = FALSE;
    }

    return 0;
}

LRESULT CALLBACK KeyTrap(int nCode, WPARAM wParam, LPARAM lParam)
{
    gotKey = TRUE;
    return  CallNextHookEx(hook, nCode, wParam, lParam);
}

BOOL CtrlHandler(DWORD fdwCtrlType)
{
    if (fdwCtrlType == CTRL_C_EVENT)
    {
        printf("Got CTRL+C, unhooking...\n");
        UnhookWindowsHookEx(hook);
    }

    return FALSE;
}

The handle returned by SetWindowsHookEx is definitely not NULL, but for some reason KeyTrap is NEVER called at all, regardless of how many keys I try to press. I've also tried to put the callback in a DLL and use LoadLibrary on runtime, but this also gives the exactly the same result.

I'm new to all this Win32 programming, so it may very well be a very silly mistake.

Thanks very much!

(PS: Code's running on Win7. No access to an actual keyboard at the moment, but have tried generating keystrokes from the on-screen keyboard, remote (RDP) input, and the hardware hotkeys on the tablet. Could this be the issue?)


Solution

  • The issue is that your console application doesn't have a message loop to process the hook messages.

    Replace your while(1) loop with the following and see if that works:

       MSG msg;
       while( GetMessage( &msg, NULL, 0, 0 ) != 0 ) 
       {
          TranslateMessage( &msg );
          DispatchMessage( &msg );
    
          if(gotKey) 
            printf("Got Key!\n");        
    
          gotKey = FALSE;
       }