Reputation: 49
So I'm trying to get my MouseHook working. I need to register when WM_LBUTTONUP happens.
HHOOK MouseHook;
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam){
PKBDLLHOOKSTRUCT k = (PKBDLLHOOKSTRUCT)(lParam);
if (wParam == WM_LBUTTONUP)
{
Msg(":)");
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
...
MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, hInstance, 0);
...
MSG msg;
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Problem now is if I call Sleep() anywhere in my program it will freeze the mouse. How can I get around this? Is it possible to run the hook in a separate thread?
Upvotes: 0
Views: 900
Reputation: 612934
A low level hook is called in the context of the thread that registers it. So, register the hook from a different thread. You'll need that thread to pump its message queue for the hook to work.
A bigger problem is your calling Sleep
in your main thread. That will stop your UI from being responsive. You'll need to stop doing that.
Upvotes: 1
Reputation: 20063
This is because low level keyboard and mouse hooks requires a message pump n order for the hook procedure to be invoked on an event. When you call Sleep
it prevents the thread from processing the message queue. When this happens the hook procedure cannot being called and the windows hooking mechanism to block until the next time the message pump is executed.
You can indeed manage the hook in a separate thread as the hook callback is executed in the context of the thread that installs the hook. You should also make sure that you are not calling Sleep
from within the hook callback or perform any more operations than necessary otherwise the it may be automatically removed by the system. From Remarks section of MSDN documentation on LowLevelMouseProc
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
...
The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key: HKEY_CURRENT_USER\Control Panel\Desktop
The value is in milliseconds. If the hook procedure times out, the system passes the message to the next hook. However, on Windows 7 and later, the hook is silently removed without being called. There is no way for the application to know whether the hook is removed.
Example:
#include <windows.h>
#include <iostream>
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
std::cout << "hook called" << std::endl;
return CallNextHookEx(0, nCode, wParam, lParam);
}
DWORD WINAPI ThreadProc(void*)
{
SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
int main()
{
CreateThread(NULL, 0, ThreadProc, NULL, 0, 0);
Sleep(20000);
}
Upvotes: 2