GetMessage和PeekMessage的区别及PostMessage(hWnd, WM_QUIT, 0, 0)消息

本文详细介绍了Windows消息处理中的两个关键函数:GetMessage和PeekMessage的区别与应用,包括它们的工作原理、参数作用、返回值含义及在退出应用程序、线程管理等场景中的具体用法。

 

关于这个两个函数的详细信息:
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、调用模态对话框的窗口处理函数会被阻塞,但是新的消息循环仍然可以调用父窗口的消息处理函数,所以,发送给父窗口的新消息仍然可以被及时处理。

 

 

转载于:https://www.cnblogs.com/mlog/archive/2011/07/19/2456358.html

在基于 C++98 封装 WinAPI 的窗口类 `Widget` 实现模态化显示窗口时,模态窗口退出时通常不需要发送 `WM_QUIT` 消息。 `WM_QUIT` 消息的作用是终止应用程序的消息循环,当主消息循环接收到 `WM_QUIT` 消息时,`GetMessage` 函数会返回 0,从而使消息循环结束,应用程序退出。而模态窗口只是在当前线程内暂时阻止用户与其他窗口进行交互,其退出不应该导致整个应用程序退出。 在 `Widget::exec()` 函数的实现中,当模态窗口关闭时,仅需要销毁窗口(调用 `DestroyWindow`),而不需要发送 `WM_QUIT` 消息。在窗口过程函数 `WndProc` 中,处理 `WM_CLOSE` 消息时调用 `DestroyWindow` 销毁窗口,处理 `WM_DESTROY` 消息时不调用 `PostQuitMessage`,这样可以保证模态窗口退出后,原有的消息系统能继续正常运行。以下是相关代码示例: ```cpp class Widget { private: HWND m_hWnd; public: void exec() { HWND hParent = ::GetParent(m_hWnd); if (hParent && ::IsWindow(hParent)) { ::EnableWindow(hParent, FALSE); } ::ShowWindow(m_hWnd, SW_SHOWNORMAL); ::UpdateWindow(m_hWnd); MSG msg; while (::IsWindow(m_hWnd)) { if (::GetMessage(&msg, NULL, 0, 0) <= 0) { if (msg.message == WM_QUIT) { ::PostQuitMessage(static_cast<int>(msg.wParam)); } break; } ::TranslateMessage(&msg); ::DispatchMessage(&msg); } if (hParent && ::IsWindow(hParent)) { ::EnableWindow(hParent, TRUE); ::SetActiveWindow(hParent); } } static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CLOSE: ::DestroyWindow(hWnd); return 0; case WM_DESTROY: return 0; default: return ::DefWindowProc(hWnd, message, wParam, lParam); } } }; ``` 在上述代码中,模态窗口关闭时,只是销毁了窗口,并没有发送 `WM_QUIT` 消息,这样可以保证原有的消息循环继续运行,不会影响整个应用程序的正常退出逻辑。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值