views:

119

answers:

1

I have successfully gotten my low-level mouse hook code to work, but there are some behaviors I'm observing that I don't quite understand. Everything works fine if I spawn a thread which installs the mouse hook. When i no longer need it running, I let the thread get destroyed automatically as I exit the program, and I imagine I can easily terminate the thread explicitly. However this makes me uneasy because I won't end up calling UnhookWindowsHookEx to free the mouse hook resources.

So I tried to reverse the logic in my testing program. I try spawning a thread which sleeps for a bit, and then writes to a global variable. Then I call the hook installing routine from the primary thread. In here is a loop which checks the global variable and exits the loop when appropriate. Then it will be able to clean up after itself. Here is the relevant code:

static int willQuit = 0;
unsigned WINAPI MouseProcessingProc (void *param) {
 try { // will catch exceptions and not propagate them
  HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc,
    NULL, 0);
  if (mousehook == NULL) printf("Mousehook error %u\n",GetLastError());

  while(true) {
   MSG msg;
   if (GetMessage(&msg,0,0,0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
   if (willQuit) { printf("willQuit no longer 0!\n"); break; }
   printf("Looped\n");
  }
  willQuit = 0;
  UnhookWindowsHookEx(mousehook);

  printf("Procedure completed without exceptional events.\n");
 } catch (const std::string& s) {
  printf("String exception: %s\n", s.c_str());
 } catch (int i) {
  printf("Int exception: %d\n", i);
 } catch (...) {
  printf("Unknown default exception!\n");
 }
 printf("Exiting thread execution.\n");
 return 0;
}

void spawn() {
 printf("Spawning Mouse thread\n");
 _beginthreadex(NULL,0,MouseProcessingThreadProc,NULL,0,0);
}

void run() {
 printf("Running Mouse routine\n");
 MouseProcessingThreadProc(0);
}

void stop() {
 printf("Stopping Mouse routine\n");
 willQuit = 1;
}

unsigned WINAPI threadproc(void *param) {
    Sleep(500);
    printf("Spawned thread says 3");
    Sleep(500);
    printf("2");
    Sleep(500);
    printf("1\n");
    Sleep(500);
    printf("Spawned thread calls stop now -->\n");
    stop();
}

int main() {
    _beginthreadex(NULL,0,threadproc,NULL,0,0); // waiter and stopper thread
    run(); // become the mousehook thread
    printf("Completed\n");
    return 0;
}

Now what's happening is that the little message polling loop I have (the while loop) never really returns from the GetMessage call, so it can never reach the point where it checks willQuit. I have verified this with those printf's and gdb. Why does GetMessage not return? Is there a better way to set up my mouse hook thread? Or am I trying to do something that I am not supposed to do?

thanks for reading.

A: 

In your stop() routine, after setting the willQuit variable, you will also need to POST any message to the thread running MouseProcessingProc, so GetMessage will return. See PostThreadMessage API.

EDIT: You could also use an event, or other sync object, instead of using windows messages and the message pump. So the message pump would get replace by something like WaitForSingleObject, some kernel object that you can signal, such as an event.

Chris O
This makes a lot of sense. Now it seems more appropriate to just create my own custom thread message, and when the mouse handling threads receive the quit message they can quit on their own. A very natural solution to the problem!
Steven Lu