解决方案 »

  1.   

    一、Windows中有一个系统消息队列,对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。windows系统把应用程序的输入事件传递给各个窗口,每个窗口有一个函数,称为窗口消息处理函数。窗口消息处理函数处理各种用户输入,处理完成后再将控制权交还给系统。
      

  2.   

    其实简单点就是:windows用维护一个系统消息队列,然后程序的事件都会先发送给系统消息队列(这里都说是队列消息),然后系统消息队列根据得到的消息的窗口句柄,发送给相应的程序。每个程序中都 有一个消息循环,里面可以来处理消息,然后处理消息的函数叫窗口消息处理函数。
      

  3.   

    每个线程有个消息队列,线程的消息队列可以使用GetMessage取出
      

  4.   

    每创建线程,MFC就会创建消息队列来进行消息处理
      

  5.   

    请问一个windows应用程序在运行时,操作系统会为它建立多少条消息队列?每一条消息队列里的消息是如何发送的?应用程序是如何接收的?默认的,每个线程拥有4个消息队列,分别是:程序消息队列,系统消息队列,发送消息队列,应答消息队列。程序消息队列是最重要的消息队列,绝大多数我们知道的消息都是从这个队列里提取的。系统消息队列用于存放原始的硬件事件如鼠标事件,键盘事件等等。发送消息队列和应答消息队列用于SendMessage和PostMessage跨线程发送消息,类似于一种同步机制。
    应用程序通过通过GetMessage和PeekMessage从消息队列里提取消息。提取的顺序是先检查应答消息队列,然后是程序消息队列,最后是系统消息队列。当没有任何消息时,检查定时器,如果当前线程的定时器到期,产生WM_TIMER消息。如果也没有定时器,检查是否存在无效区域。如果有,则返回一个WM_PAINT消息。这就是WM_PAINT消息为什么出现在所有消息后的原因。msg结构进入程序后,由DispatchMessage函数根据消息的hwnd字段发送到目标窗口。由目标窗口类过程函数首先得到处理机会。对于一个win32 api程序来说,就能够在WIndowProc里响应这些消息了。
     
    哇擦,累 纯手打。还有 一点,并不是所有程序都有4个消息队列的。控制台程序没有程序消息队列,不过当你在控制台里调用PeekMessage函数时,会强制系统为该控制台线程附加一个程序消息队列。
      

  6.   

    每个GUI线程1个消息队列,详细的机制可以看看这篇文章:
    http://zhidao.baidu.com/link?url=_anOtXLjucxCRWMUjAOsUZ7tl7sxuZdmi0odX00cOHO0m8xAAsJEgGx1IXobG8XsbWt1BD1gA8ld_B1NnEaSfSOWm6F-fOIX-5RA7mwo-Nm
      

  7.   

    理解讨论之前请先学会如何观察!使用Spy++软件。顺便向9楼致敬!
      

  8.   


    非常感谢这位大师的详细解答,这正是我想要的答案,小弟我还存在以下问题,希望大师能继续深入解答,感谢!1、程序消息队列里存放的是不是对方调用SendMessage、PostMessage和PostThreadMessage函数发送过来的消息?如果不是,那是什么?
    2、系统消息队列里存放的是不是由操作系统自动发送过来的WM_开头的窗口消息?如果不是,那是什么?
    3、发送消息队列里存放的是不是我方调用SendMessage、PostMessage和PostThreadMessage函数发送的消息,但是还没有来得及发出去的消息?如果不是,那是什么?
    4、应答消息队列里存放的是不是我方响应对方调用SendMessage函数的返回值,但是还没有来得及发出去的?如果不是,那是什么?
    5、WM_PAINT消息不是由操作系统自动发送的,是由GetMessage和PeekMessage函数自动产生的?如果不是,那是什么?
      

  9.   

    1:基本正确。线程调用PostMessage和PostThreadMessage向本线程发送的消息确实进入了程序消息队列,不过SendMessage是一个特殊的函数,它直接调用目标窗口的类过程函数,并等待处理结果。因此它发送的消息不会进入任何消息队列。
    2:也可以说基本正确。不过,以WM_开头的消息绝大多数都不是由硬件事件产生的。硬件事件消息的范围只是那么几个:比如WM_LBUTTONDOWN这样明显的带有硬件标记的消息。系统队列初始存放的是一些硬件事件,这些事件到消息的转换还有一个过程。
    3:和1一样,SendMessage除外。发送消息队列和应答消息读ui咧主要用于跨线程调用PostMessage和PostThreadMessage。接收方使用发送消息队列存储外来消息。
    4:发送方使用应答消息队列来存放回应字段。每当一个线程向另外一个线程发送消息后,它会设置自己的应答消息队列,设置的内容一般与发送的消息对应。应答消息队列存在的必要性是由于PostThreadMessage和PostMessage这些异步发送函数的特性,他们在发送完消息后,并不等待目标线程的处理结果,而是立刻返回,那么总 要有一种机制让发送方能够得到接收方对消息的处理结果吧?当接收方处理完消息后,接收方委托系统通知发送方,并同时清除自己的发送消息队列。系统通知发送方后,发送方就能够得到接收方对消息的处理结果,然后发送方也清理自己的应答消息队列中的消息。
    5,、正确的。系统完全可以发送一条WM_PAINT消息给程序,但这和GetMessage与PeekMessage返回有什么区别呢?不如将这个逻辑交给这两个函数来实现。说实话各种消息的迷惑性实在挺大的,很难清楚的了解到到底哪个消息是由谁产生的,又是怎么运作的。我也是花了一段时间查资料才了解个大概,有不准确的地方希望网友多多指教
      

  10.   


    大师这个回复我看了很多天,终于有些理解了,我还想在问下几个问题:
    1、控制台程序有没有系统消息队列?如果有,有什么作用?
    2、可否解释下Sendmessage()函数的发送、处理、返回过程?最后,建议这个位大师能把这个问题写成完整的文档,并保持文档定期更新,这样以后再有人问到这个样的问题,你就可以直接让他看文档,还可以帮助更多的人,谢谢!
      

  11.   

    大师这个回复我看了很多天,终于有些理解了,我还想在问下几个问题:
    1、控制台程序有没有系统消息队列?如果有,有什么作用?
    2、可否解释下Sendmessage()函数的发送、处理、返回过程?最后,建议这个位大师能把这个问题写成完整的文档,并保持文档定期更新,这样以后再有人问到这个样的问题,你就可以直接让他看文档,还可以帮助更多的人,谢谢!这些天太忙了,也没上论坛来看看。第一个问题我也没有研究过,如果有兴趣的话可以用内核调试器到内核看一下THREADINFO这个结构体,它里面的4个线程队列指针可以告诉你想要的答案。关于SendMessage这个我上面也说过了,它直接调用目标窗口类过程函数,然后挂起发起者线程,直到目标窗口类过程函数返回。它是一个消息的传送者但并不负责消息的处理。写文档是不行的, 能力有限时间有限,我所掌握的也只是在网上找的一部分资料再加上一定的测试。自己掌握的也并不是很详细哼透彻,写文档岂不是贻笑大方?正所谓满瓶子不溢半瓶子咣当,我在这咣当这么久并不代表我掌握的多,只是回答这些问题的时候自己对概念的理解也透彻起来,原来没有总结的顺便总结了一下。
      

  12.   


    大师这个回复我看了很多天,终于有些理解了,我还想在问下几个问题:
    1、控制台程序有没有系统消息队列?如果有,有什么作用?
    2、可否解释下Sendmessage()函数的发送、处理、返回过程?最后,建议这个位大师能把这个问题写成完整的文档,并保持文档定期更新,这样以后再有人问到这个样的问题,你就可以直接让他看文档,还可以帮助更多的人,谢谢!这些天太忙了,也没上论坛来看看。第一个问题我也没有研究过,如果有兴趣的话可以用内核调试器到内核看一下THREADINFO这个结构体,它里面的4个线程队列指针可以告诉你想要的答案。关于SendMessage这个我上面也说过了,它直接调用目标窗口类过程函数,然后挂起发起者线程,直到目标窗口类过程函数返回。它是一个消息的传送者但并不负责消息的处理。写文档是不行的, 能力有限时间有限,我所掌握的也只是在网上找的一部分资料再加上一定的测试。自己掌握的也并不是很详细哼透彻,写文档岂不是贻笑大方?正所谓满瓶子不溢半瓶子咣当,我在这咣当这么久并不代表我掌握的多,只是回答这些问题的时候自己对概念的理解也透彻起来,原来没有总结的顺便总结了一下。我个人觉得你可以慢慢写,没必要一次性就写到最好,你可以在发现问题后做及时修改和完善,我一般都是在这么干的,要不然我学到的很多东西都会忘记,别人问我的东西我有时也懒得讲,我就统一用文档搞定了。