看过多篇文章,包括MSDN,可对于GetMessage和PeekMessage的原理还不是很清晰。
《技术内幕4》原文中提到“Windows决定哪个消息属于我们的程序,当一个消息需要被处理时,GetMessage函数就返回。如果没有消息被发出来,我们的程序就被挂起,而其他的程序就可以运行;当一个消息终于到达时,我们的程序被唤醒。”我们的程序从系统消息队列里GetMessage,为什么由Windows决定是属于哪个程序,当有属于自己的消息时,TranslateMessage并DispatchMessage。而
"PeekMessage,即使没有消息到达程序,它也会马上返回,从而使函数继续执行,如果有一个消息的话,函数将被暂停,消息控制函数被调用,在它返回后,笨重函数再继续执行。”这两种方法我还是觉得乱乱的,我表达能力差,无法把我的困惑清楚的表达出来,反正高手们有谁对这一块全然理解透彻的话,告诉小弟,真诚求教。高分相赠。

解决方案 »

  1.   

    用消息来触发程序?不是用Windows根据CPU的执行时间周期来传递控制权的吗?我是这么理解的,当前程序获得CPU控制权后从消息队列里Get or PeekMessage,有自己的消息则响应,消息队列里的消息是对谁来说的,当前程序线程还是整个Windows系统?
    PS:关于消息队列有没有介绍的比较详细点的书,请推荐一下。VC我看了深入浅出和技术内幕,可感觉还不爽,有没有再深入点,深点的知识,也推荐一下。
      

  2.   

    GetMessage是同步的
    PeekMessage是异步的
      

  3.   

    GetMessage是要等有消息时才会从调用中返回
    PeekMessage发完消息后,不管目标是否响应,都会从函数调用中返回
      

  4.   

    GetMessage
    The GetMessage function retrieves a message from the calling thread's message queue and places it in the specified structure. This function can retrieve both messages associated with a specified window and thread messages posted via the PostThreadMessage function. The function retrieves messages that lie within a specified range of message values. GetMessage does not retrieve messages for windows that belong to other threads or applications. Res
    An application typically uses the return value to determine whether to end the main message loop and exit the program. The GetMessage function only retrieves messages associated with the window identified by the hWnd parameter or any of its children, as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax parameters. If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread via PostThreadMessage. GetMessage does not retrieve messages for windows that belong to other threads nor for threads other than the calling thread, even if hWnd is not NULL. Thread messages, posted by the PostThreadMessage function, have a message hWnd value of NULL. If wMsgFilterMin and wMsgFilterMax are both zero, GetMessage returns all available messages (that is, no range filtering is performed). The WM_KEYFIRST and WM_KEYLAST constants can be used as filter values to retrieve all messages related to keyboard input; the WM_MOUSEFIRST and WM_MOUSELAST constants can be used to retrieve all mouse messages. If the wMsgFilterMin and wMsgFilterMax parameters are both zero, the GetMessage function returns all available messages (that is, without performing any filtering). GetMessage does not remove WM_PAINT messages from the queue. The messages remain in the queue until processed. Note that the function return value can be nonzero, zero, or -1. Thus, you should avoid code like this:while (GetMessage( lpMsg, hWnd, 0, 0)) ... 
     
    The possibility of a -1 return value means that such code can lead to fatal application errors. ////////////
    PeekMessage
    The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified structure. Res
    Unlike the GetMessage function, the PeekMessage function does not wait for a message to be placed in the queue before returning. PeekMessage retrieves only messages associated with the window identified by the hWnd parameter or any of its children as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax parameters. If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread making the call. (PeekMessage does not retrieve messages for windows that belong to other threads.) If hWnd is –1, PeekMessage only returns messages with a hWnd value of NULL, as posted by the PostThreadMessage function. If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns all available messages (that is, no range filtering is performed). The WM_KEYFIRST and WM_KEYLAST constants can be used as filter values to retrieve all keyboard messages; the WM_MOUSEFIRST and WM_MOUSELAST constants can be used to retrieve all mouse messages. The PeekMessage function normally does not remove WM_PAINT messages from the queue. WM_PAINT messages remain in the queue until they are processed. However, if a WM_PAINT message has a null update region, PeekMessage does remove it from the queue.
      

  5.   

    去看《深入浅出MFC》里面有详细阐述!
      

  6.   

    GetMessage类似于SendMessage. 有消息才会传回, 否则是阻塞的...,同时并不删除原队列的消息.
    PeekMessage 类似于PostMessage ,没有消息也立即返回, 同时有选项选择是否删除原消息...
      

  7.   

    深入浅出mfc 的说法:这两函数性质不同, 它们都是到消息队列中抓消息,如果抓不到, 程序的主执行线程会被程序系统挂起.当操作系统再次回来照顾这一执行线程时,发现消息队列仍然是空的,这时候两个api函数的行为就不同了:GetMessage会过门不入,于是操作系统再去照顾其它人
    PeekMessage会取回控制权, 使程序得以执行一段时间
      

  8.   

    CSDN - 专家门诊 - VC/MFC 基础类问题  
     回复 | 推荐 | 收藏 | 专题 | 公告 | 管理 | 保存 | 关闭窗口   
     
     
    主  题:  ●●关于消息循环,对你们来说可能很简单,但它困惑我很久了。请进来看看吧●● 
    作  者:  whjpn (常盘平)  
    等  级:    
    信 誉 值:  100 
    所属论坛:  VC/MFC 基础类 
    问题点数:  50 
    回复次数:  22 
    发表时间:  2002-11-27 14:19:34 
       
     
       
    我做了一个基于对话框的MFC程序,在对话框的BUTTON1按钮下面写了如下代码:
    void CMyProjDlg::OnButton1() 
    {
    do
    {
    MSG message;
    if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
    {
    if (message.message == WM_QUIT)
    ::PostQuitMessage(0);
    ::TranslateMessage(&message);
    ::DispatchMessage(&message);
    }
    //use up CPU cycles;
    }while(true);
    }
    当我点击BUTTON1时,该代码开始运行。此时如果我按对话框右上角的“X”,可以看到对话框消失了,但进程列表里我的这个程序还没有退出。我跟踪了一下,好像在我按“X”之后,程序没有得到WM_QUIT消息,所以就没有执行::PostQuitMessage(0).
    我想问的是,为什么我按“X”之后,程序没有得到WM_QUIT消息?
    /////////////////////////////////////////////////////////////////
    回复人: paul2002() ( ) 信誉:100  2002-11-28 17:19:00  得分:0 
     
     
      void CMyProjDlg::OnButton1() 
    {
    do
    {
    MSG message;
    if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
    {
    if (message.message == WM_QUIT)
                                {
    ::PostQuitMessage(0);
                                         return;
                                 }
    ::TranslateMessage(&message);
    ::DispatchMessage(&message);
    }
    //use up CPU cycles;
    }while(true);
    }void CMyProjDlg::OnClose() 
    {
    // CDialog::OnClose();
    ::DefWindowProc(m_hWnd,WM_CLOSE,0,0);

    }