c++qthookevent-loopmouse-hook

Running a C++ Event Loop WITHOUT using QT


I have been trying to develop a background Windows application in c++ to capture system wide keystrokes and mouse clicks (no I'm not writing a keystroke logger, just keystroke rates!). For this I have figured out that I need to use Windows Hooks and I came across this excellent video which gave me a basic example. Unfortunately, it uses the QT framework and for licencing (and other time based) reasons, this is not available to me currently. All I need to be able to do is adapt the code so that it does not require the "return a.exec()" line (which I believe is what starts off the event loop).

A comment on the youtube video appeared to have the answer: "For those who don't use QT, just add while(GetMessage(NULL, NULL, 0, 0)); instead of a.exec(), QT loop. It should work fine"

But could not get this solution to work. Would be very grateful for help in getting the code below to execute as an event loop without depending on the QT framework.

#include <QtCore/QCoreApplication>
#inlcude <QDebug>
#include <iostream>
#include <Windows.h>

HHOOK hHook = NULL;

using namespace std;

LRESULT CALLBACK MyLowLevelKeyBoardProc(int nCode, WPARAM wParam, LPARAM     lParam)
{
    qDebug() << "A Key was pressed";
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv); //need to remove this QT dependency

    hHook = SetWindowsHookEx(WH_KEYBOARD_LL, MyLowLevelKeyBoardProc, NULL, 0);
    if (hHook==NULL){
        qDebug() << "Hook Failed";
    }

    return a.exec(); //need to remove this QT dependency
}

Here is an attempt (only showing main()) of re-writing using a message loop and removing the QT references:

int main(int argc, char *argv[])
{
   MSG msg = NULL;
   while (GetMessage(msg, NULL, NULL, NULL)){   
    hHook = SetWindowsHookEx(WH_KEYBOARD_LL, MyLowLevelKeyBoardProc, NULL, 0);
    if (hHook==NULL){
        qDebug() << "Hook Failed";
    }

   }
}

Solution

  • This is a sample that works.

    #include <Windows.h>
    #include <stdlib.h>
    #include <iostream>
    
    HHOOK g_hHook = NULL;
    DWORD g_HookThread;
    
    LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        PKBDLLHOOKSTRUCT hookstruct = reinterpret_cast<PKBDLLHOOKSTRUCT>(lParam);
        std::cout << hookstruct->vkCode << std::endl;
        if( wParam == WM_KEYUP ) {
            if( hookstruct->vkCode == VK_ESCAPE ) {
                PostThreadMessage( g_HookThread, WM_QUIT, NULL, NULL );
            }
        }
        return CallNextHookEx( g_hHook, nCode, wParam, lParam );
    }
    
    int main()
    {
        g_HookThread = GetCurrentThreadId();
        g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
    
        MSG msg;
        while( GetMessage(&msg, NULL, NULL, NULL) ) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        UnhookWindowsHookEx(g_hHook);
        return 0;
    }
    

    edit: I originally commented that whatpulse switched to directinput, but now they seem to have switched back to lowlevel hooks.