如何处理来自多个窗口的消息
How to handle messages from multiple windows
所以我有多个窗口正在运行,我想处理所有这些窗口的消息,这样它们就不会挂起。到目前为止,我已经尝试了多种方法:
1)把它做成一个线程(有点愚蠢,但我试过了):
auto ProcessThread(
std::vector<HWND> Windows
) -> void
{
for (;;)
{
MSG Msg1 = decltype(Msg1){0x00};
MSG Msg2 = decltype(Msg2){0x00};
GetMessageW(&Msg1, Windows.at(0), 0, 0);
GetMessageW(&Msg2, Windows.at(1), 0, 0);
TranslateMessage(&Msg1);
TranslateMessage(&Msg2);
DispatchMessageW(&Msg1);
DispatchMessageW(&Msg2);
}
return;
}
...
std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
HANDLE hThread = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(ProcessThread),
&Windows, 0, nullptr);
while (WAIT_TIMEOUT == WaitForSingleObject(hThread, 1000)) {}
CloseHandle(hThread);
2)只是塞满第二个消息循环
MSG Msg1 = decltype(Msg1){0x00};
MSG Msg2 = decltype(Msg2){0x00};
while (GetMessageW(&Msg1, Hwnd1, 0, 0) && GetMessageW(&Msg2, Hwnd2, 0, 0))
{
TranslateMessage(&Msg1);
TranslateMessage(&Msg2);
DispatchMessageW(&Msg1);
DispatchMessageW(&Msg2);
}
3)第二个的其他变体
到目前为止,所有这些都使我的窗户无法移动,并给了我加载光标。
有什么想法吗?
您的代码存在几个问题:
-
ProcessThread()
被声明为CreateThread()
所有错误,编译器通常会为此对你尖叫,但你正在使用错误的类型转换来使编译器安静而不是修复错误。 因此,ProcessThread()
将无法在运行时正确接收vector
。ProcessThread()
需要看起来更像这样:DWORD WINAPI ProcessThread(LPVOID lpParam) { std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam); ... return 0; } ... HANDLE hThread = CreateThread(..., &ProcessThread, &Windows, ...);
-
线程的消息循环都是错误的。 每次循环迭代调用
GetMessage()
一次,并且根本不指定任何过滤HWND
(请参阅过滤窗口消息的危险)。 它将从消息队列中提取下一条可用消息,然后您可以将其传递给DispatchMessage()
,以将消息发送到相应的WndProc
进行进一步处理。DWORD WINAPI ProcessThread(LPVOID lpParam) { std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam); MSG Msg; while (GetMessageW(&Msg, 0, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } return 0; }
-
您正在创建一个工作线程,只是为了等待它终止,而不并行执行任何其他操作。 这使得工作线程完全无用。 你需要摆脱那个线程,特别是考虑到...
-
。您在与创建窗口的线程不同的线程中运行消息循环。 你根本做不到! 窗口具有线程相关性。
(Get|Peek)Message()
仅接收与调用线程关联的窗口的消息,因此只有创建窗口的线程才能接收该窗口的消息。
你过度思考你的代码设计。 您可以将其大大简化为:
std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;
while (GetMessageW(&Msg, 0, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
如果lpScreen.m_WindowHandle
和lpPopup.m_WindowHandle
是调用线程中唯一可用的窗口,那么您甚至根本不需要vector
!
但是,如果您只对处理特定窗口的消息感兴趣,这确实会带来问题。 上面的代码将接收调用线程中所有窗口的消息。 如果这不是您想要的,那么您可以(但不应该!)过滤vector
中的特定窗口,例如:
std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;
for(auto h : Windows)
{
while (PeekMessageW(&Msg, h, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
}
但是,如果您不小心,这可能会导致其他窗口的消息匮乏。
否则,您只需使用单独的线程来创建和处理您感兴趣的窗口。
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 由于无效的 ValidateRgn() 子窗口不会收到WM_PAINT消息
- MFC 中的窗口消息管理:添加基类调用是否是强制性的?
- 输出窗口中消息的可视化工作室源
- 为什么初始化 Wintab 扩展后没有收到WT_PACKETEXT窗口消息?
- 与WM_DPICHANGED消息一起发送的建议窗口大小太大
- 如何处理窗口的消息?
- 在弹出窗口中管理CEF客户端区域的窗口消息
- 在Internet Explorer_Server(IE9)中处理窗口消息
- 使用智能指针在窗口消息中将对象作为 WPARAM 传递
- 将窗口消息发送到控制台应用程序
- 是否可以捕获翻译/调度消息循环中的窗口消息/事件
- 调整窗口大小时不断发送窗口消息WM_SIZING
- 正在发送转发窗口消息
- 对于单个实例应用程序,只允许使用单个窗口消息框
- Win32:更多"object oriented"窗口消息处理系统
- 异步代理和窗口消息
- Windows (c++)上窗口消息的问题(延迟)
- WinAPI窗口消息似乎被插件窃取-如何修复
- 在 COleControl 中未处理的 LButtonUp 窗口消息