18

I've been trying some things with hooks, and I don't understand why hooks must be used with a message queue

hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
        TranslateMessage(&msg);
        DispatchMessage(&msg);
}
UnhookWindowsHookEx(hook);

Why doesn't something like this work ?

hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);
cin >> aKey;
UnhookWindowsHookEx(hook);

Using boost threads, and a barrier doesn't work either. Why can't the waiting between the hook and unhook be done in another manner ?

EDIT:

I did a mistake when I created this sample, I create a WH_KEYBOARD_LL hook, not WH_KEYBOARD, (I don't think it makes a big difference)

Also the loop never executes only waits on the GetMessage function.

The loop executes only when I post the quit message PostThreadMessage(id, WM_QUIT, 2323, NULL); so I don't understand what does it do beside waiting, is there some internal processing ?

RELATED:

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup

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

Community
  • 1
  • 1

2 Answers2

36

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)

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • So, If I understand this correctly, Windows can only call my callback while in a Get/PeekMessage() call ? –  Sep 18 '11 at 10:04
  • 2
    You understand it correctly. There is no other way to safely inject calls into a thread, it has to be idle. This is why message loops exist. – Hans Passant Sep 18 '11 at 10:08
  • @HansPassant to clarify, are you suggesting that for global hooks like WH_KEYBOARD named pipes can be used to "pass" info back to my own program and that program does not need a message pump? – dave Feb 24 '14 at 08:01
3

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

Community
  • 1
  • 1
shf301
  • 31,086
  • 2
  • 52
  • 86
  • thanks for the links, I went trough all of them but I still don't understand what GetMessage does beside waiting. In my case (console application) the only time it executes it when I post the quit message to the thread. –  Sep 18 '11 at 08:35
  • Also, since GetMessage waits, doesn't this mean that the console is not pumping any message till my quit message ? –  Sep 18 '11 at 08:38
  • See Han's answer - Windows will only call your thread back when it knows that its idle. And if the thread is blocked in GetMesasge() Windows knows that it isn't doing anything – shf301 Sep 18 '11 at 20:26