【问题标题】:SetWindowsHookEx for WH_KEYBOARD_LL handler PostThreadMessage message not received?未收到 WH_KEYBOARD_LL 处理程序 PostThreadMessage 消息的 SetWindowsHookEx?
【发布时间】:2021-03-23 23:55:59
【问题描述】:

我设置了一个处理程序来在短时间内捕捉击键,同时为窗口使用私人消息循环。虽然它有效,但如果我尝试PostThreadMessage,窗口永远不会收到消息?

回调看起来像(我尝试了其他消息,这个示例带有私人消息):

LRESULT CALLBACK LLKeyboardHookProc(int ncode, WPARAM wp, LPARAM lp) 
{
  if (ncode ==  HC_ACTION) {
    if (wp==WM_KEYDOWN) {
      KBDLLHOOKSTRUCT *kbs=reinterpret_cast<KBDLLHOOKSTRUCT*>(lp);
      if (kbs->vkCode==VK_ESCAPE) {
        PostThreadMessage (GetCurrentThreadId(), UWM_MYCLOSEMESSAGE, 0, 0);
      }
    }
  }
  return CallNextHookEx(0, ncode, wp, lp);
}

HHOOK kbhook = SetWindowsHookEx(WH_KEYBOARD_LL, LLKeyboardHookProc, GetModuleHandle(NULL), 0);

WS_EX_LAYERED 窗口的消息循环如下所示:

  while (IsWindow(hwnd)) {
    MSG msg;
    while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg);
    }
    // let MFC do its idle processing
    LONG lIdle=0;
    while (AfxGetApp()->OnIdle(lIdle++));

    WaitMessage();
  }

  // clean up
  UnhookWindowsHookEx(kbhook);

我现在将其更改为使用 volatile 变量来关闭窗口,但我真的很想给它发送一条消息。如果没有锁,使用全局 HWND 不会是线程安全的,所以不想那样做。

附:我确实检查了 PostThreadMessage 结果,它不是 FALSE(我添加它们时没有调试消息),所以它似乎将它发布在某个地方。

【问题讨论】:

  • 当你还创建了一个窗口时,千万不要使用 PostThreadMessage(),像调整窗口大小这样简单的事情会导致消息丢失。但是,很明显,您在消息循环中没有任何代码来处理消息。 DispatchMessage() 什么都不做,没有窗口。不要使用它。

标签: winapi setwindowshookex


【解决方案1】:

PostThreadMessage()thread 消息发布到队列,而不是 window 消息。您的消息循环忽略 thread 消息,仅调度 window 消息。窗口永远不会看到 thread 消息,因此您需要直接在消息循环中处理此类消息,例如:

MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    if (msg.hwnd == NULL && msg.message == UWM_MYCLOSEMESSAGE) { // <-- add this
        // do something...
    }
    else {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
}

然而,正如 Hans Passant 在评论中所说:

当您还创建了一个窗口时,切勿使用 PostThreadMessage(),调整窗口大小这样简单的操作会导致消息丢失

Raymond Chen 发表了几篇关于这个主题的博客文章:

Thread messages are eaten by modal loops

Watching thread messages disappear

Rescuing thread messages from modal loops via message filters

Why do messages posted by PostThreadMessage disappear?

您可以尝试使用 WH_MSGFILTER 钩子,就像 Raymond 演示的那样。但解决此问题的最佳方法是根本不发布 thread 消息,而是发布 window 消息。让您的键盘挂钩使用PostMessage()(甚至SendMessage())到您的应用拥有的HWND,然后您可以在该窗口的消息过程中处理该消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2019-06-29
    相关资源
    最近更新 更多