Windows API不会退出

由于某种原因,我closures这个窗口后,我的程序不会退出,并进入一个无限循环。 这个问题的解决scheme似乎将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); } 

WM_QUIT不会发送到任何窗口,只是放在线程的消息队列中,没有HWND ,这就是为什么它不符合您的过滤器。

看一下MSDN中的GetMessage和PostQuitMessage

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

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

这是一个很好的机会来锻炼你的“搜索MSDN文档”能力:

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

指示终止应用程序的请求,并在应用程序调用PostQuitMessage函数时生成。 此消息导致GetMessage函数返回零。

WM_QUIT消息不与一个窗口相关联,因此决不会通过窗口的窗口过程来接收。 它只能通过GetMessagePeekMessage函数获取。

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

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

hWnd [in,可选]类型: HWND

消息将被检索的窗口的句柄。 该窗口必须属于当前线程。

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

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

还有很多关于Windows程序通常如何处理来自MSDN的消息的更多信息 。


作为附注,窗口关闭事件的消息是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 )。