Windows API不会退出

时间:2013-12-15 18:22:00

标签: c++ windows winapi user-interface

由于某些原因,在我关闭此窗口后,我的程序不会退出并进入无限循环。这个问题的解决方案似乎是将GetMessage(& message,handel,0,0)更改为GetMessage(& message,NULL,0,0)。但是,我不明白为什么会这样。有人可以解释一下。另外,我不知道为什么我会调用UpdateWindow(handel),因为窗口会在没有它的情况下显示。

#include <iostream>
#include <Windows.h>

using namespace std;

LRESULT CALLBACK EventHandler(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, PSTR args, int cmd)
{
    MSG message;
    HWND handel;
    WNDCLASS win_class;

    win_class.style = CS_HREDRAW | CS_VREDRAW;
    win_class.cbClsExtra = 0;
    win_class.cbWndExtra = 0;
    win_class.lpszClassName = "Window";
    win_class.hInstance = inst;
    win_class.hbrBackground = GetSysColorBrush(COLOR_3DDKSHADOW);
    win_class.lpszMenuName = NULL;
    win_class.lpfnWndProc = EventHandler;
    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClass(&win_class);
    handel = CreateWindow(win_class.lpszClassName, "Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 250, NULL, NULL, inst, NULL);
    ShowWindow(handel, cmd);
    UpdateWindow(handel);

    //Loop does not end.
    while(GetMessage(&message, handel, 0, 0))
    {
         cout << "LOOP" << endl;
         DispatchMessage(&message);
    }
    return WM_QUIT;
}

LRESULT CALLBACK EventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static long long count = 0;
    count++;
    cout << "CALL #" << count << endl;
    if(msg == WM_DESTROY)
    {
         PostQuitMessage(0);
         return 0;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

3 个答案:

答案 0 :(得分:2)

WM_QUIT未发送到任何窗口,只是放在线程的邮件队列中,没有HWND,这就是为什么它与您的过滤器不匹配。

答案 1 :(得分:1)

查看MSDN中的GetMessagePostQuitMessage

如果hWnd函数的参数GetMessage为NULL,则GetMessage将检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中其hwnd值为的所有消息NULL

PostQuitMessage函数将WM_QUIT消息发布到线程的消息队列,而不是当前窗口。

答案 2 :(得分:0)

这是练习“搜索MSDN文档”能力的好机会:

首先,让我们查看WM_QUIT的文档:

  

表示终止应用程序的请求,并在何时生成   应用程序调用PostQuitMessage函数。这条信息   导致GetMessage函数返回零。

     

...

     

WM_QUIT 消息与窗口无关,因此会   永远不会通过窗口的窗口程序接收。它被检索   只能通过 GetMessage PeekMessage 功能。

然后,让我们查看GetMessage()的文档:

  

从调用线程的消息队列中检索消息。该   函数调度传入的已发送消息,直到发布消息为止   可供检索。

     

...

     

hWnd [in,optional]输入: HWND

     

要检索其消息的窗口句柄。窗户   必须属于当前线程。

     

如果hWnd NULL ,GetMessage将检索任何窗口的消息   属于当前线程,以及当前的任何消息   线程的消息队列,其hwnd值为NULL(参见MSG   结构体)。因此,如果hWnd为NULL,则为窗口消息和线程   消息被处理。

因此,您希望NULL用作GetMessage()的窗口句柄,而不是handel,因为WM_QUIT与任何窗口都没有关联。

MSDN还有plenty more information about how Windows programs typically handle messages


作为旁注,窗口关闭事件的消息是WM_CLOSE,这反过来会导致窗口被默认销毁。 WM_DESTROY表示你的窗口已经被摧毁了。因此,如果您想拦截关闭事件(比如要求您的用户保存任何更改),您将处理WM_CLOSE事件。

另外,如GetMessage()文档所示,您实际上应该将GetMessage()循环看起来像这样:

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

因为GetMessage()实际上可以返回1,0或-1(尽管它返回BOOL)。