未收到 WH_KEYBOARD_LL 处理程序 PostThreadMessage 消息的 SetWindowsHookEx?
SetWindowsHookEx for WH_KEYBOARD_LL handler PostThreadMessage message not received?
我设置了一个处理程序来在短时间内捕获击键,同时为 window 使用私人消息循环。虽然它有效,但如果我尝试 PostThreadMessage
window 从未收到消息?
回调看起来像(我尝试了其他消息,这个示例是一条私人消息):
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
window 的消息循环看起来像:
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);
我暂时将其更改为使用可变变量来关闭 window,但我真的很想向它发送消息。如果没有锁,使用全局 HWND 将不是线程安全的,所以不想那样做。
P.S。我确实检查了 PostThreadMessage 结果,它不是假的(当我添加它们时没有调试消息)所以它似乎 post 它在某处。
PostThreadMessage()
post向队列发送 线程 消息,而不是 window 消息.您的消息循环忽略 thread 消息,仅发送 window 消息。 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 在评论中所说:
Never use PostThreadMessage() when you also created a window, something as simple as resizing the window causes the message to get lost.
Raymond Chen post编辑了几篇关于这个主题的博客文章:
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 演示的那样。但解决这个问题的最好方法是根本不 post 一个 thread 消息, post 一个 window 消息代替。让你的键盘挂钩使用 PostMessage()
(甚至 SendMessage()
)到你的应用程序拥有的 HWND
,然后你可以在那个 window 的消息过程中处理消息。
我设置了一个处理程序来在短时间内捕获击键,同时为 window 使用私人消息循环。虽然它有效,但如果我尝试 PostThreadMessage
window 从未收到消息?
回调看起来像(我尝试了其他消息,这个示例是一条私人消息):
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
window 的消息循环看起来像:
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);
我暂时将其更改为使用可变变量来关闭 window,但我真的很想向它发送消息。如果没有锁,使用全局 HWND 将不是线程安全的,所以不想那样做。
P.S。我确实检查了 PostThreadMessage 结果,它不是假的(当我添加它们时没有调试消息)所以它似乎 post 它在某处。
PostThreadMessage()
post向队列发送 线程 消息,而不是 window 消息.您的消息循环忽略 thread 消息,仅发送 window 消息。 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 在评论中所说:
Never use PostThreadMessage() when you also created a window, something as simple as resizing the window causes the message to get lost.
Raymond Chen post编辑了几篇关于这个主题的博客文章:
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 演示的那样。但解决这个问题的最好方法是根本不 post 一个 thread 消息, post 一个 window 消息代替。让你的键盘挂钩使用 PostMessage()
(甚至 SendMessage()
)到你的应用程序拥有的 HWND
,然后你可以在那个 window 的消息过程中处理消息。