Welcom to zougangx's blog

坚持...积累... 编程是一门技术,更加是一门艺术

PostQuitMessage(WM_QUIT) 退不出程序

今天写了一个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);
    }
}
阅读更多
个人分类: C++
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭