Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Global Keyboard Hook

Tags:

c++

dll

winapi

I am attempting to create a global keyboard hook that will be used to read keystrokes for a hotkey program I am creating and I've run into a few problems. First is that whenever I activate my hook the keyboard becomes sluggish. There is almost a full second delay between each character that comes on the screen. The second issue is that any code I write in the DLL callback function never gets executed.

Here is my code:

DLL cpp file

#include<Windows.h>
#include "keyDLL.h"

using namespace std;

LRESULT CALLBACK HookProcedure(int code, WPARAM wParam, LPARAM lParam)
{
    return CallNextHookEx(0, code, wParam, lParam);
}

DLL header file

#include "windows.h"

extern "C" __declspec(dllexport) LRESULT CALLBACK HookProcedure(int code, WPARAM wParam, LPARAM lParam);

hook CPP file

#include<Windows.h>
#include<iostream>
using namespace std;

HHOOK WINAPI SetWindowsHookEx(_In_  int idHook, _In_  HOOKPROC lpfn, _In_  HINSTANCE hMod, _In_  DWORD dwThreadId
static HINSTANCE dllHandle;
HOOKPROC address;
static HHOOK keyboard_hook;

int main()
{
    dllHandle = LoadLibrary(TEXT("keyDLL.dll"));
    address = (HOOKPROC)GetProcAddress(dllHandle, "HookProcedure");
    cout << address << endl << dllHandle << endl;
    keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, address, dllHandle, 0);

    system("pause");
}

This version of the code is just a super simple cut down version that only sets up the keyboard hook. I took out all other code in my attempts to find out what was causing the issues. From my understanding of hooks (which isn't all that much apparently) this code should hook the keyboard but do nothing with the keystrokes. I'm not understanding why it slows my keyboard down so much. I used dumpbin to ensure there was no name mangling on the DLL export functions. I am running windows 8 64 bit and both my DLL and my exe files are compiled as 64 bit. When I cout the address and dllHandle variables I get memory addresses so I know at least part of the code is working. Any help would be appreciated, thanks.

like image 314
Phil Gibson Avatar asked Dec 25 '22 20:12

Phil Gibson


1 Answers

Another approach would be this code below:

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <iostream>
#include <windows.h>
#include <stdio.h>

HHOOK hKeyboardHook;

__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam)
{
    DWORD SHIFT_key=0;
    DWORD CTRL_key=0;
    DWORD ALT_key=0;


    if  ((nCode == HC_ACTION) &&   ((wParam == WM_SYSKEYDOWN) ||  (wParam == WM_KEYDOWN)))      
    {
        KBDLLHOOKSTRUCT hooked_key =    *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = {0};

        int i = GetKeyNameText(dwMsg,   (lpszKeyName+1),0xFF) + 1;

        int key = hooked_key.vkCode;

        SHIFT_key = GetAsyncKeyState(VK_SHIFT);
        CTRL_key = GetAsyncKeyState(VK_CONTROL);
        ALT_key = GetAsyncKeyState(VK_MENU);

            printf("Keycode = %c\n",key);

        if (key >= 'A' && key <= 'Z')   
        {

            if  (GetAsyncKeyState(VK_SHIFT)>= 0) key +=32;

            /*********************************************
            ***   Hotkey scope                         ***
            ***   do stuff here                        ***
            **********************************************/

            if (CTRL_key !=0 && key == 'y' )
            {
               MessageBox(NULL, "CTRL-y was pressed\nLaunch your app here", "H O T K E Y", MB_OK); 
               CTRL_key=0;

               //do stuff here




            }

            if (CTRL_key !=0 && key == 'q' )
            {
                MessageBox(NULL, "Shutting down", "H O T K E Y", MB_OK); 
               PostQuitMessage(0);
            }




            SHIFT_key = 0;
            CTRL_key = 0;
            ALT_key = 0;

        }

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

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

DWORD WINAPI my_HotKey(LPVOID lpParm)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR) lpParm); 
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx (  WH_KEYBOARD_LL, (HOOKPROC) KeyboardEvent,   hInstance,  NULL    );
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

int main(int argc, char** argv)
{
    HANDLE hThread;
    DWORD dwThread;

    printf("CTRL-y  for  H O T K E Y  \n");
    printf("CTRL-q  to quit  \n");

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)   my_HotKey, (LPVOID) argv[0], NULL, &dwThread);

       /* uncomment to hide console window */
    //ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);

    if (hThread) return WaitForSingleObject(hThread,INFINITE);
    else return 1;

}
like image 200
Software_Designer Avatar answered Dec 28 '22 09:12

Software_Designer