Why must SetWindowsHookEx be used with a windows message queue

Solution 1:

The low-level hooks, WH_KEYBOARD_LL and WH_MOUSE_LL are different from all the other hooks. They don't require a DLL to be injected into the target process. Instead, Windows calls your hook callback directly, inside your own process. To make that work, a message loop is required. There is no other mechanism for Windows to make callbacks on your main thread, the callback can only occur when you've called Get/PeekMessage() so that Windows is in control.

A global hook like WH_KEYBOARD is very different. It requires a DLL and the callback occurs within the process that processes the keyboard message. You need some kind of inter-process communication to let your own program be aware of this. Named pipes are the usual choice. Which otherwise of course requires that this injected process pumps a message loop. It wouldn't get keyboard messages otherwise.

Favor a low-level hook, they are much easier to get going. But do pump or it won't work. And beware of timeouts, if you're not responsive enough then Windows will kill your hook without notice.

Understanding the low-level mouse and keyboard hook (win32)

Solution 2:

Windows Hooks hook the Windows message loop: http://msdn.microsoft.com/en-us/library/ms644959#wh_keyboardhook

The WH_KEYBOARD hook enables an application to monitor message traffic for WM_KEYDOWN and WM_KEYUP messages about to be returned by the GetMessage or PeekMessage function. You can use the WH_KEYBOARD hook to monitor keyboard input posted to a message queue.

Console applications don't pump messages themselves - the console process does. So it won't work unless the process has a message loop.

See:

How can I set up a CBT hook on a Win32 console window?

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup