由于某种原因,我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消息不与一个窗口相关联,因此决不会通过窗口的窗口过程来接收。 它只能通过GetMessage或PeekMessage函数获取。
然后,让我们查看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
)。