首页>Program>source

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

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
  if (nCode >= 0) {
    if (wParam == WM_RBUTTONDOWN) printf("right mouse down\n");
    if (wParam == WM_RBUTTONUP) printf("right mouse up\n");
  }
  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\n");
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
#ifdef TEST
  Sleep(50);
#endif
}

所以一切都在这里工作,除非我 #define TEST 放入 Sleep ,鼠标变得异常缓慢,这是可以预料的,如果我突然只允许鼠标每秒更新20次.如果没有睡眠,我会将CPU固定在100%.但这现在还可以(如果我使用 GetMessage )。

据我所知,低级挂钩通过上下文切换到安装它的进程,然后向进程发送某种消息以使其执行挂钩回调来工作.但是,令我有些困惑的是为什么我的程序永远不会print" msg recvd",但是每当我单击鼠标右键时它都会print" down / up".这使我得出结论,我的 MouseHookProcPeekMessage期间被调用 呼叫.碰巧是某种特殊的讯息,而 PeekMessage 返回0。但是我仍然需要致电 PeekMessage 或等效的内容。

由于我的程序需要做很多事情,所以我显然无法权衡消息泵送循环(调用 PeekMessage的循环) ),方法是调用另一个需要50毫秒才能返回的函数.如何在我的程序上多线程化以保持鼠标的响应能力,同时又进行一些繁重的工作? 在多线程win32程序中,仍然只有一个消息队列,对吧?

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

最新回答
  • 13天前
    1 #

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

    为什么必须将SetwindowsHookEx与windows消息队列一起使用

  • 13天前
    2 #

    我问您是否放置 MouseHookProc 在DLL中,因为尝试将其放在EXE内是一个典型的错误.我也是很多年前做到的。

    首先,如何阅读http://msdn.microsoft.com/zh-cn/library/ms644990.aspx:

    SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.

    因此,您必须将其放置在DLL中.确切地说,如果要同时支持32位和64位平台,则必须实现两个dll:一个32位和64位DLL.但为什么? 以及如何 有效吗?

    如果您在EXE中执行以下代码,则

    SetWindowsHookEx
    

    您向user32.dll请求发出请求,以将syshook.dll注入同一windows工作站上的所有其他进程中(dll不会注入到其他服务和进程 通过快速用户切换登录的用户).然后user32.dll调用 HINSTANCE hinstDLL = LoadLibrary(TEXT("c:\\myapp\\syshook.dll")); HOOKPROC hkprcMouse = (HOOKPROC)GetProcAddress(hinstDLL, "MouseHookProc"); HHOOK hhookMouse = SetWindowsHookEx( WH_MOUSE_LL, hkprcMouse, hinstDLL, 0); 在不同的进程中访问syshook.dll.然后,如果功能 LoadLibrary 将被调用,将在处理鼠标消息的过程的上下文中被调用.如果该过程不是控制台应用程序,则代码类似

    MouseHookProc
    

    无法正常工作。

    所以我希望现在您会迷惑为什么必须放置 printf("right mouse down\n");

  • 13天前
    3 #

    而不是这样做:

    MouseHookProc
    

    将其切换为:

    if (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
        printf("msg recvd\n");
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    Sleep(50);
    

    这将允许您的应用继续处理队列中的所有消息,直到队列为空(例如不睡觉), while (PeekMessage(&msg,0,0,0,PM_REMOVE)) { // Add this potentially... if (msg.message == WM_QUIT) break; printf("msg recvd\n"); TranslateMessage(&msg); DispatchMessage(&msg); } Sleep(10); 当应用程序为"空闲"时,放弃一些CPU时间。

  • 13天前
    4 #

    then 应该驻留在dll中,否则您将无法捕获"全局"输入(http://msdn.microsoft.com/en-us/library/ms997537.aspx)

    关于循环-您可以像这样修改它:

    MouseHookProc
    
    while(true) { MSG msg; while (PeekMessage(&msg,0,0,0,PM_REMOVE)) { printf("msg recvd\n"); TranslateMessage(&msg); DispatchMessage(&msg); } #ifdef TEST DoStuff(); Sleep(50); #endif }

  • c:在L1和L2处预取数据
  • R 330在windows上安装软件包:找不到gcc错误