MFC中PeekMessage與GetMessage的區別

一、PeekMessage與GetMessage的對比

GetMessage的主要功能是從消息隊列中“取出”消息,消息被取出以後,就從消息隊列中將其刪除;而PeekMessage的主要功能是“窺視”消息,如果有消息,就返回true,否則返回false。

也可以使用PeekMessage從消息隊列中取出消息,這要用到它的一個參數(UINT wRemoveMsg),如果設置爲PM_REMOVE,消息則被取出並從消息隊列中刪除;如果設置爲PM_NOREMOVE,消息就不會從消息隊列中取出。

相同點:
PeekMessage函數與GetMessage函數都用於查看應用程序消息隊列,有消息時將隊列中的消息派發出去。

不同點:

無論應用程序消息隊列是否有消息,PeekMessage函數都立即返回,程序得以繼續執行後面的語句(無消息則執行其它指令,有消息時一般要將消息派發出去,再執行其它指令)。


GetMessage函數只有在消息隊列中有消息時返回,如果隊列中無消息就會一直等,直至下一個消息出現時才返回。在等的這段時間,應用程序不能執行任何指令。

二、實例

PeekMessage

//PeekMessage查看消息隊列中是否有消息,如果沒有則執行畫矩形DrawRectangle,有消息則先把消息發配出去,

PeekMessage函數獲取並派發消息出去,然後繼續畫矩形DrawRectangle。

nt WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("RandRect") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Random Rectangles"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;

        //用於替換的部分  
    
    while (TRUE)
     {
          if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
          {
               if (msg.message == WM_QUIT)
                    break ;
               TranslateMessage (&msg) ;
               DispatchMessage (&msg) ;
          }
          else
               DrawRectangle (hwnd) ;
     }
    //用於替換的部分 
     return msg.wParam ;
}

如果換成

GetMessage

while (TRUE)
     {
          if (GetMessage (&msg, NULL, 0, 0))
          {
               if (msg.message == WM_QUIT)
                    break ;
               TranslateMessage (&msg) ;
               DispatchMessage (&msg) ;
           DrawRectangle (hwnd) ;
          } 
          else
                break;
     }

則應用程序產生一個消息(鼠標移動、改變窗體大小等),在窗體內畫一個隨機生成的矩形,無消息產生時,窗體無變化。

三、總結

如果GetMessage從消息隊列中取不到消息,則線程就會被操作系統掛起,等到OS重新調度該線程時,兩者的性質不同:使用GetMessage線程仍會被掛起,使用PeekMessage線程會得到CPU的控制權,運行一段時間。

GetMessage每次都會等待消息,直到取到消息才返回;而PeekMessage只是查詢消息隊列,沒有消息就立即返回,從返回值判斷是否取到了消息。

我們也可以說,PeekMessage是一個具有線程異步行爲的函數,不管消息隊列中是否有消息,函數都會立即返回。而GetMessage則是一個具有線程同步行爲的函數,如果消息隊列中沒有消息的話,函數就會一直等待,直到消息隊列中至少有一條消息時才返回。

所以,從它們的不同點上來看,PeekMessage函數有點像“乞丐行乞”,有你就施捨點,沒有也不強求。GetMessage函數有點像“強盜打劫”,有你得給,沒有我就等你什麼時候有了再給,這段時間我什麼都不幹,我就等你。

參考:

https://www.cnblogs.com/simonryan/p/3936447.html

https://blog.csdn.net/gencheng/article/details/9376881?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章