8.windows消息机制(三)

1.消息队列

  消息队列用于存放消息的一个队列,消息在队列中先入先出。所有窗口程序都具有消息队列,程序可以从队列中获取消息。

2.消息队列的类型

  系统消息队列 - 由系统维护的消息队列,存放系统产生的消息,例如鼠标、键盘等。

  程序消息队列 - 属于每一个应用程序(线程)的消息队列,由应用程序(线程)维护。

3.消息队列机制

  所有的消息都先进系统的消息队列,系统每隔一段时间就发到每个进程的消息队列。

  例如:

    当鼠标、键盘产生消息时,会将消息存放到系统消息队列。系统会根据存放的消息,找到对应窗口(进程)的消息队列。

    将消息投递到程序(进程)的消息队列。

  那么系统是怎么准确地发到某个进程的消息队列呢?

  首先通过消息的窗口句柄,找到保存窗口数据的内存地址,然后拿到当前程序实例句柄(即进程)。

  PostMessage,是把消息发到系统队列,为什么?

    因为如果不发到系统队列,直接发到进程队列,那么可能造成后产生的消息先处理。

  SendMessage,把消息既不发到系统消息队列也不发到进程消息队列,那么发到哪里?

     发到消息的窗口处理函数(其实内部是直接调用窗口处理函数),内部简单执行过程:

    SendMessage(...)

    {

      进过一系列匹配找到窗口处理函数

      return WndProc(...);

    }

4.队列消息和非消息队列的关系

  (1)使用关系

     队列消息:消息的发送和获取,都是通过消息队列完成。

     非队列消息:消息的发送和获取,是直接调用消息的窗口处理完成。

  (2)队列消息 - 消息发送后,先放入系统队列,然后通过消息循环,从队列中获取。

     GetMessage - 从消息队列中获取消息(只能从本进程的队列获取消息)

     PostMessage - 将消息投递到系统队列

     常见队列消息:WM_PAINT、键盘、鼠标、定时器等。

  (3)非消息队列 - 消息发送时,直接查找消息接收窗口的窗口处理函数,调用处理函数,完成消息处理。 

     SendMessage - 直接将消息发送给窗口的处理函数,并等候处理结果。

     常见非队列消息:WM_CREATE、WM_SIZE等。

5.消息循环

  GetMessage/PeekMessage - 从程序的消息队列中获取消息。

  TranslateMessage - 检查获取的消息,如果是按键消息,产生一个字符消息WM_CHAR,并放入程序的消息队列。

  DispatchMessage - 根据消息找到窗口处理函数,调用窗口处理函数,完成消息处理。

  重点讲一下GetMessage/PeekMessage,目前我们所了解的是GetMessage会到进程的消息队列获取消息,没有就阻塞;如果有,获取消息后返回。

  (1)GetMessage在本程序(进程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND,ID范围),不满足就不会取出消息,

             否则从队列取出消息并返回。

  (2)如果本程序(进程)消息队列没有消息,向系统消息队列获取属于本程序的消息。如果系统消息队列的当前消息属于本程序,系统将消息转发到

             本程序的消息队列。

  (3)如果系统消息队列没有消息,检查所有窗口需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT消息,取得消息并返回。

  (4)如果没有重新绘制区域,检查定时器。如果有到时的定时器,产生WM_TIMER消息,取得并返回。

  (5)如果没有到时的定时器消息,整理程序的资源、内存等。

  (6)此时,GetMessage会继续等候下一条消息,而PeekMessage返回FALSE,交出程序的控制权。

  注意:GetMessage如果获取到WM_QUIT,函数返回FALSE。

6.消息发送

  SendMessage - 用于非队列消息的发送。发送消息到指定的窗口,并等候对象将消息处理,然后返回消息执行结果。

  PostMessage - 用于队列消息的发送。将消息放到系统消息队列,立刻返回。无法获知消息是否被对方处理。

  

 

posted @ 2016-06-16 22:59  甩锅侠  阅读(247)  评论(0编辑  收藏  举报