Home > Net >  How to listen to all keypresses in Winapi and cancel some of them?
How to listen to all keypresses in Winapi and cancel some of them?

Time:03-02

I'm trying to write an keyboard software debounce program in C( ) for my crappy keyboard that double-clicks.

I apparently need to set a hook to WM_KEYBOARD_LL, but I a) couldn't do it, I have "invalid handle" errors and b) don't know how to cancel the keypresses, as I also want to do this for gaming.

How would I properly implement this?

Thanks in advance!

EDIT: Here is the non-working code I found somewhere

#include "windows.h"
#include <iostream>
using namespace std;

HHOOK hookHandle;

LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam);

int main(int argc, char *argv[])
{

  hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, keyHandler, NULL, 0);

  if (hookHandle == NULL)
  {
    cout << "ERROR CREATING HOOK: ";
    cout << GetLastError() << endl;
    getchar();
    return 0;
  }

  MSG message;

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

  cout << "Press any key to quit...";
  getchar();

  UnhookWindowsHookEx(hookHandle);

  return 0;
}

LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
  cout << "Hello!" << endl;

  // Checks whether params contain action about keystroke
  if (nCode == HC_ACTION)
  {
    cout << ((KBDLLHOOKSTRUCT *)lParam)->vkCode << endl;
  }

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

I am compiling it with Mingw-W64 on Linux, but error reproduces on MSVC and Mingw-W64 on Windows.

CodePudding user response:

I apparently need to set a hook to WM_KEYBOARD_LL, but I ... couldn't do it, I have "invalid handle" errors

Per the SetWindowsHookEx() documentation:

An error may occur if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process.

Which is exactly what you are doing.

So, if your goal is to hook every running process globally (ie, dwThreadId=0), you need to pass a non-NULL HMODULE to the hMod parameter. Low-level hooks are not required to be implemented as DLLs, so you should be able to use the GetModuleHandle() function (for instance, with either lpModuleName=NULL or lpModuleName="kernel32.dll" should suffice).

[I] don't know how to cancel the keypresses

Per the LowLevelKeyboardProc documentation:

Return value

...

If nCode is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_KEYBOARD_LL hooks will not receive hook notifications and may behave incorrectly as a result. 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.

  • Related