GetMessage和PeekMessage的区别及PostMessage(hWnd, WM_QUIT, 0, 0)消息
关于这个两个函数的详细信息:
BOOL GetMessage(
LPMSG lpMsg, // 一个MSG的指针
HWND hWnd, // 一般为当前窗口的句柄
UINT wMsgFilterMin, // 指定被检索的最小消息值的整数
UINT wMsgFilterMax // 指定被检索的最大消息值的整数
);
如果第三,四个参数都为零,则取所有的消息。
如果出现错误,比如参数一或参数而指向的指针或句柄无效,则会返回-1.
BOOL PeekMessage(
LPMSG lpMsg, // 一个MSG的指针
HWND hWnd, //
UINT wMsgFilterMin, //
UINT wMsgFilterMax, // 前四个参数和GetMessage的一样
UINT wRemoveMsg // 取完消息要做的操作
);
wRemoveMsg:确定消息如何被处理。此参数可取下列值之一:
PM_NOREMOVE:PeekMessage处理后,消息不从队列里除掉。
PM_REMOVE:PeekMessage处理后,消息从队列里除掉,一般都是采用这种删除的方法。
两个函数主要有以下两个区别:
1.GetMessage将等到有合适的消息时才返回,而PeekMessage只是撇一下消息队列。(立刻返回)
2.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。
在Windows的内部,GetMessage和PeekMessage执行着相同的代码。而两者最大的不同之处则体现在没有任何消息返回到应用程序的情况下。在此种情况下,
PeekMessage会返回一个空值到应用程序,GetMessage会在此时让应用程序休眠。
PostQuitMessage 向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息使用例子如
//处理主窗口的消息. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 菜单选项命令响应: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0);//调用函数PostQuitMessage来处理退出应用程序。 break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
WM_QUIT消息非常特殊,她使GetMessage函数返回0,从而结束了消息循环,所以在GetMessage中发送PostMessage(hWnd, WM_QUIT, 0, 0);无法在消息处理函数中响应WM_QUIT消息事件(EeekMessage可以).
所以不要直接发送PostMessage(hWnd, WM_QUIT, 0, 0);MSDN中也做了以下说明:
This message indicates a request to terminate an application and is generated when the application calls the PostQuitMessage function. It causes the GetMessage function to return zero.
但理解上面后可以使用这个方法退出子线程 代码片段为 TThread.Execute方法
主线程发送PostMessage(hWnd, WM_QUIT, 0, 0) 子线程退出,
while(true) do begin if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin if (Msg.message=WM_QUIT) then begin //WM_QUIT事件处理 Break; //退出线程 end; end; DoTheHardWork();//干活 end
如果是
while GetMessage(Msg, 0, 0, 0) do//收到PostMessage(hWnd, WM_QUIT, 0, 0)退出while循环 begin if (Msg.message=WM_USER+1000) then //任务来了 begin DoTheHardWork(); SendFeedBackToMainWin; end; end;
另:
WM_TIMER消息和WM_PAINT消息都是低优先级的\,窗口的消息队列中有其他消息的情况下,这两个的消息就得不到及时处理,被推迟投递,
模态对话框和非模态对话框的消息循环
1、非模态对话框和父窗口共享当前线程的消息循环
2、模态对话框新建一个新的消息循环,并由当前消息循环派发消息,而父窗口。模态对话框屏蔽了用户对它父窗口的操作,但是不是在消息循环里面屏蔽,所以给父窗口发送消息,父窗口还是可以接收得到。
3、调用模态对话框的窗口处理函数会被阻塞,但是新的消息循环仍然可以调用父窗口的消息处理函数,所以,发送给父窗口的新消息仍然可以被及时处理。