Win32应用程序中的窗口将无法正常关闭

时间:2015-09-27 01:21:58

标签: c winapi

原始问题:

我有一个窗口,在创建后无法立即关闭,尽管我的窗口过程函数能够检测到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参数?

2 个答案:

答案 0 :(得分:6)

正确编写的消息循环永远不会向窗口过程发送WM_QUIT消息,当GetMessage()收到WM_QUIT时返回0时,它将简单地打破循环1}}消息:

GetMessage function

  

如果函数检索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上有记录:

Closing the Window

以下是该页面的流程图:

flow chart

至于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,则窗口消息和线程消息都会被处理。

究竟是什么原因导致窗口移动以使其随后的关闭尝试成功,但我仍然无法理解。