我有一个窗口,在创建后无法立即关闭,尽管我的窗口过程函数能够检测到WM_CLOSE
消息,并调用PostQuitMessage
并让Windows继续使用{处理窗口消息{1}}。
但是,在通过拖动标题栏移动窗口后,它似乎能够正常关闭。
我的窗口过程函数的代码如下:
DefWindowProc
除了将LRESULT CALLBACK OnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_QUIT:
{
printf("WM_QUIT\n");
break;
}
case WM_CLOSE:
{
printf("WM_CLOSE\n");
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(handle, message, wParam, lParam);
}
消息发送到我的窗口或使用WM_MOVE
案例块中的exit(0)
之外,我怎样才能确保我的窗口在创建后立即关闭?
将WM_CLOSE
传递给NULL
的{{1}}参数后,而不是我的窗口句柄,窗口现在正常关闭,因此回答了我之前的问题。
因此,为什么hWnd
函数以前没有使用唯一窗口提供的句柄检索GetMessageW
消息,而不是使用GetMessageW
作为WM_QUIT
参数?
答案 0 :(得分:6)
正确编写的消息循环永远不会向窗口过程发送WM_QUIT
消息,当GetMessage()
收到WM_QUIT
时返回0时,它将简单地打破循环1}}消息:
如果函数检索WM_QUIT以外的消息,则返回值为非零。
如果函数检索WM_QUIT消息,则返回值为零。
如果有错误,则返回值为-1。例如,如果hWnd是无效的窗口句柄或lpMsg是无效指针,则函数将失败。要获取扩展错误信息,请调用GetLastError。
在回复WM_CLOSE
时,您应该直接致电DestroyWindow()
而不是PostQuitMessage()
(DefWindowProc(WM_CLOSE)
的默认行为是为您致电DestroyWindow()
) 。您需要一个WM_DESTROY
处理程序,然后应该调用PostQuitMessage()
:
LRESULT CALLBACK OnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
{
printf("WM_CLOSE\n");
DestroyWindow(handle);
return 0;
}
case WM_DESTROY:
{
printf("WM_DESTROY\n");
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(handle, message, wParam, lParam);
}
这在MSDN上有记录:
以下是该页面的流程图:
至于GetMessage()
问题,如果您仔细阅读GetMessage()
和PostQuitMessage()
的文档,则会看到WM_QUIT
发布的PostQuitMessage()
消息}不是窗口消息。将非NULL HWND
传递给GetMessage()
仅检索来自PostMessage()
和SendMessage()
的特定HWND
1 的消息。 GetMessage()
会忽略任何不适合HWND
的邮件,其中包含来自PostThreadMessage()
和PostQuitMessage()
的帖子邮件。将NULL HWND
传递给GetMessage()
可以返回任何待处理的消息,包括WM_QUIT
。
1 这很危险,BTW:The dangers of filtering window messages
答案 1 :(得分:0)
当我在循环中使用主窗口的句柄作为第二个参数调用 GetMessage()
时,我遇到了这个确切的问题:
GetMessage(&msg, hMainWindow, 0, 0)
而不是 NULL 来指定我要处理整个线程/应用程序实例的消息:
GetMessage(&msg, NULL, 0, 0)
WM_CLOSE 消息会导致 WM_QUIT 消息,但 GetMessage() 仅在查找特定窗口的消息时会忽略这些消息。来自documentation:
<块引用>如果 hWnd 为 NULL,则 GetMessage 检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中 hwnd 值为 NULL 的任何消息(请参阅 MSG 结构)。因此,如果 hWnd 为 NULL,则窗口消息和线程消息都会被处理。
究竟是什么原因导致窗口移动以使其随后的关闭尝试成功,但我仍然无法理解。