了解低级键鼠钩子(win32)

时间:2023-04-12
本文介绍了了解低级键鼠钩子(win32)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在尝试捕获全局鼠标和键盘输入.

I'm trying to capture global mouse and keyboard input.

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
  if (nCode >= 0) {
    if (wParam == WM_RBUTTONDOWN) printf("right mouse down
");
    if (wParam == WM_RBUTTONUP) printf("right mouse up
");
  }
  return CallNextHookEx(0, nCode, wParam, lParam);
}

HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
while(true) {
  MSG msg;
  if (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
    printf("msg recvd
");
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
#ifdef TEST
  Sleep(50);
#endif
}

所以这里一切正常,除非我 #define TEST 放入 Sleep,鼠标变得非常迟钝,如果我突然只允许鼠标每秒更新 20 次.如果没有睡眠,我将 CPU 固定在 100%.但这暂时没问题(如果我使用 GetMessage 就会消失).

So everything works here, except if I #define TEST to put in the Sleep, the mouse becomes incredibly sluggish, as might be expected if I suddenly only allow the mouse to update 20 times a second. And without the sleep, I am pegging the CPU at 100%. But that's okay for now (that goes away if I use GetMessage).

现在据我所知,低级钩子通过上下文切换到安装它的进程来工作,然后向进程发送某种消息以让它执行钩子回调.不过,让我有点困惑的是,为什么我的程序永远不会打印msg recvd",但每当我单击鼠标右键时,它就会打印鼠标右键向下/向上".这使我得出结论,我的 MouseHookProcPeekMessage 调用期间被调用.它恰好是某种特殊的消息,PeekMessage 返回 0.但我仍然需要调用 PeekMessage 或一些等效的.

Now as I understand it, the low-level hooks work by context-switching to the process which installed it, and then sending the process some kind of message to let it execute the hook callback. What confuses me a little, though, is why my program will never print "msg recvd", but it prints "right mouse down/up" whenever i click the right mouse button. This leads me to conclude that my MouseHookProc is being invoked during the PeekMessage call. It just happens to be some kind of special message and PeekMessage returns 0. But I still need to call PeekMessage or some equivalent.

由于我的程序需要做很多事情,我显然不能通过调用另一个需要 50 毫秒返回的函数来减轻我的消息泵循环(调用 PeekMessage 的那个).我如何多线程处理我的程序以保持鼠标响应,同时做一些繁重的工作?在多线程的win32程序中,仍然只有一个消息队列,对吗?

Since my program needs to do a bunch of things, I clearly can't weigh down my message pumping loop (the one that calls PeekMessage) by calling another function that takes, say 50ms to return. How might I multithread my program to maintain mouse responsiveness while simultaneously doing a little heavy lifting? In a multithreaded win32 program, there is still just one message queue, right?

更新:在阅读了 MS 的文档后,我想我知道我应该做什么是正确的.我应该在我的应用程序中生成一个线程,它调用 SetWindowsHookEx 来注册鼠标钩子,然后坐在它自己的消息循环中,系统将负责将鼠标更新发送到这个线程.它可以在 MouseHookProc 中自由地做任何它想做的事情,而我的应用程序的其余部分将独立运行.

Update: After reading up on MS's documentation I think I know what the right thing for me to do is. I should just spawn a thread in my application which calls SetWindowsHookEx to register the mouse hook, and then sit around in its own message loop, and the system will take care of sending the mouse updates to this thread. It will be free to do whatever it wants within the MouseHookProc, and the rest of my application will run independently.

推荐答案

问题在于你的消息循环,因为你使用 PeekMessage(),它消耗了 100% 的 CPU 周期.即使您不轮询消息,Windows 也知道如何使钩子保持活动状态,请使用 GetMessage() 来解决您的问题.使用 Sleep(1) 也可以解决您的问题,但在这里不是必需的.

The problem is your message loop, it burns 100% CPU cycles because you use PeekMessage(). Windows knows how to keep the hook alive even if you don't poll for messages, use GetMessage() to solve your problem. Using Sleep(1) will solve your problem too but is not necessary here.

为什么必须将 SetWindowsHookEx 与 Windows 消息队列一起使用

这篇关于了解低级键鼠钩子(win32)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:如何在 Win32 上快速枚举目录? 下一篇:如何创建虚拟文件?

相关文章