None of the provided answers helped me solve my problem, but I found the answer myself. Here it is.
Using SetWindowsHookEx() with WH_KEYBOARD_LL was the correct approach. However, the other parameters to SetWindowsHookEx() are unintuitive:
- The last parameter, "dwThreadId",
needs to be 0.
- The second-last parameter, "hMod", needs to point to some DLL. I used
User32, which is a DLL that is always loaded anyway and is used by all
processes with a GUI. I got this idea from a CodeProject post about this.
Thus, the code looks a bit like this:
instance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookFunction, instance, 0);
The documentation is unclear about the second-last parameter. It says "The hMod parameter must be set to NULL [...] if the hook procedure is within the code associated with the current process." It doesn't state that this only applies to some types of hooks, but not to WH_KEYBOARD_LL and WH_MOUSE_LL.