PostQuitMessage(WM_QUIT) 退不出程序

来源:互联网 发布:蒙语新闻的软件下载 编辑:程序博客网 时间:2024/06/08 07:08

今天写了一个SDK程序,关闭程序时调用PostQuitMessage(WM_QUIT) ,程序没有结束,任务管理器显示其占了90%多的CPU,必须手动结束进程。

下面是退出程序Code:

LRESULT CALLBACK WindowProc (HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

完成的程序如下所示:

int WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR     lpCmdLine,
            int       nCmdShow)
{
    static TCHAR szAppName[] = TEXT ("Hello,World!");
    HWND hwnd;
    MSG msg;

    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
    wndclass.lpfnWndProc = (WNDPROC)WindowProc;
    wndclass.cbClsExtra = 0;//窗口类附加内存
    wndclass.cbWndExtra = 0;//窗口附加内存
    wndclass.hInstance = hInstance;//实例句柄
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    wndclass.hIcon = LoadIcon (NULL,IDI_APPLICATION);

    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL, "Failed to registerClass!", szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow (szAppName, TEXT("Hello,World!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage (&msg, hwnd, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

    return msg.wParam;
}

经过查看资料,发现问题出在GetMessage的参数上,把 while (GetMessage (&msg,hwnd,0,0)) 改成如下:

while (GetMessage (&msg, NULL, 0, 0)) 即可。

 

MSDN

 

GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread using the PostThreadMessage function.

中文翻译:GetMessage取得那些属于调用线程的窗口的消息和通过PostThreadMessage函数投递(发送)到调用线程的线程消息.

这样问题就明白了, GetMessage需要检索到WM_QUIT返回一个FALSE结束消息循环, 而WM_QUIT是通过PostQuitMessage(0)发送, 属于线程消息, 而非普通的窗口消息. 如果在GetMessage中用hWnd而不是NULL, 虽然WM_QUIT 消息仍会出现在程序的消息队列中,但GetMessage却无法检索到, 而且此时窗口已经被销毁了, 如果还想取得hWnd的窗口消息, 只可能发生错误( cpu占用100%, 死循环? ).

也适用于PeekMessage。

Return Values

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

Warning   Because the return value can be nonzero, zero, or -1, avoid code like this:

while (GetMessage( lpMsg, hWnd, 0, 0)) ...

The possibility of a -1 return value means that such code can lead to fatal application errors. Instead, use code like this:

BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
原创粉丝点击