代码之家  ›  专栏  ›  技术社区  ›  Steven Lu

win32-如何管理鼠标挂钩线程

  •  2
  • Steven Lu  · 技术社区  · 16 年前

    我已经成功地让我的低级鼠标挂钩代码工作,但是我观察到的一些行为我不太理解。如果我生成一个安装鼠标挂钩的线程,一切都会正常工作。当我不再需要它运行时,我让线程在我退出程序时自动销毁,我想我可以很容易地明确地终止线程。但是这让我很不安,因为我不会打电话来的 UnhookWindowsHookEx 释放鼠标挂钩资源。

    所以我试着在我的测试程序中反转逻辑。我尝试生成一个睡眠一点的线程,然后写入一个全局变量。然后我从主线程调用钩子安装例程。这里有一个循环,它检查全局变量,并在适当的时候退出循环。然后它就可以自己清理了。相关代码如下:

    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;
    }
    

    现在发生的是我的小消息轮询循环 while 循环)从不从 GetMessage 打电话,这样它就永远无法到达检查点 willQuit . 我已经用printf和gdb验证了这一点。为什么 获取消息 不回来?有没有更好的方法来设置我的鼠标钩线?或者我是想做一些不该做的事情?

    谢谢你的阅读。

    1 回复  |  直到 16 年前
        1
  •  1
  •   Chris O    16 年前

    在stop()例程中,设置willquit变量后,还需要将任何消息发送到运行mouseprocessingproc的线程,这样getmessage将返回。见 PostThreadMessage 应用程序编程接口。

    编辑: 您也可以使用事件或其他同步对象,而不是使用Windows消息和消息泵。因此消息泵将被waitForSingleObject之类的东西替换,它是一些可以发出信号的内核对象,例如事件。