我有一个多线程应用程序,在某些线程上,我正在使用 ATL 的 CWindowImpl<>
创建窗口.我有一个用作线程过程的静态方法。我需要在线程上创建一个窗口,因为我需要与线程进行一些通信以 be synchronous , 和 PostThreadMessage()
是明确异步的。当我的窗口收到 WM_DESTROY
消息(由 MESSAGE_HANDLER
宏定义的处理程序),它调用 PostQuitMessage()
,如本方法所示:
LRESULT MyATLWindowClass::OnDestroy(UINT uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL& bHandled) {
::PostQuitMessage(0);
return 0;
}
我正在使用 PostThreadMessage()
向线程发送自定义消息向线程表明是时候终止它自己了。处理该自定义消息,我调用 CWindowImpl::DestroyWindow()
方法,它似乎确实正确地破坏了窗口,就像我的 OnDestroy
正在调用消息处理程序。但是,似乎拥有线程从未收到过 WM_QUIT
。消息进行处理。下面包括我的线程过程的简化版本。
unsigned int WINAPI MyATLWindowClass::ThreadProc(LPVOID lpParameter) {
// Initialize COM on the thread
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Create the window using ATL
MyATLWindowClass new_window;
HWND session_window_handle = new_window.Create(
/* HWND hWndParent */ HWND_MESSAGE,
/* _U_RECT rect */ CWindow::rcDefault,
/* LPCTSTR szWindowName */ NULL,
/* DWORD dwStyle */ NULL,
/* DWORD dwExStyle */ NULL,
/* _U_MENUorID MenuOrID */ 0U,
/* LPVOID lpCreateParam */ NULL);
// Initialize the message pump on the thread.
MSG msg;
::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Run the message loop
BOOL get_message_return_value;
while ((get_message_return_value = ::GetMessage(&msg, NULL, 0, 0)) != 0) {
if (get_message_return_value == -1) {
// GetMessage handling logic taken from MSDN documentation
break;
} else {
if (msg.message == WD_SIGNAL_THREAD_SHUTDOWN) {
// Requested thread shutdown, so destroy the window
new_window.DestroyWindow();
} else if (msg.message == WM_QUIT) {
// Process the quit message and exit the message loop
// to terminate the thread
break;
} else {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
// Uninitialize COM on the thread before exiting
::CoUninitialize();
return 0;
}
请注意,如果我调用 DestroyWindow()
似乎并不重要或者如果我发送 WM_CLOSE
消息到窗口。在这两种情况下,线程的消息泵都没有收到 WM_QUIT。拥有线程的消息泵是否应该接收这样的消息?我对线程的消息泵和窗口的消息泵如何交互的误解在哪里?或者关于 ATL 的窗口类如何创建和管理窗口,我遗漏了什么?
最佳答案
GetMessage() 从不返回 WM_QUIT。该消息强制它返回 0,旨在终止您的消息循环。
当心使用 PostThreadMessage() 的相当大的危险。 永远不要在同时显示窗口的线程上使用它,就像您正在使用的线程一样。问题是它不接受 HWND 参数。所以只有你的消息循环可以看到消息,它不会被传递到任何带有 DispatchMessage() 的窗口。当进入模态消息循环时,这会出错,这是您无法控制的类型。就像使 MessageBox 工作的模态循环一样。或者 Windows 用来允许用户调整窗口大小的那个。或者 DialogBox() 使用的那个。等等。始终使用 PostMessage(),使用您自己的消息编号。
关于c++ - 使用 ATL 正确关闭在单独线程上创建的窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16776506/