所以我有多个正在运行的窗口,我想处理所有窗口的消息,以使它们不会挂起。到目前为止,我已经尝试了多种方法:
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)第二种的其他变化
到目前为止,所有这些都使我的窗户无法移动,并给了我正在加载的光标。
有什么想法吗?
答案 0 :(得分:0)
您的代码有几个问题:
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
(请参阅The dangers of filtering window messages)。它将从消息队列中提取下一条可用消息,然后您可以将其传递到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);
}
}
但是,如果您不小心的话,可能会导致其他窗口的邮件匮乏。
否则,您只需要使用一个单独的线程即可创建和处理您感兴趣的窗口。