• windows消息的循环机制


    首先来了解几个基本概念:

    消息:在了解什么是消息先来了解什么是事件。事件可分为几种,由输入设备触发的,比如鼠标键盘等等。由窗体控件触发的,比如button控件,file菜单等。还有就是来自Windows内部的事件。这三种称为事件。而消息,是由事件翻译而来的。事件产生消息。

    从数据结构角度来讲,消息是一种结构体。结构如下:

    typedef struct tagMSG
      
     {
      
         HWND hwnd;  //窗口句柄。
      
          UINT message;//消息类型。
      
          WPARAM wParam;//32位附加信息。
    
          LPARAM lParam;//32位附加信息。
     
         DWORD time;//消息发送时间。
     
         POINT pt;//消息发送时,鼠标所在位置。
     
     }MSG;    
    

    消息队列消息队列有两种,分为系统消息队列和应用程序消息队列产生的消息首先由Windows系统捕获,放在系统消息队列,再拷贝到对应的应用程序消息队列。32/64位系统为每一个应用程序维护一个消息队列

    消息循环:系统为每个应用程序维护一个消息循环,消息循环会不断检索自身的消息队列。每有一个消息,就用GetMessage()取出消息。

    while(GetMessage (&msg, NULL, 0, 0))//Windows消息循环。
     
     {
         TranslateMessage (&msg) ;//翻译消息,如按键消息,翻译为WM_CHAR
     
         DispatchMessage (&msg) ;//分发消息到对应窗口
     
     }
    

    GetMessage具有阻塞机制。当消息队列中没有消息时,程序非忙等,而是让权等待。当收到WM_QUIT时,GetMessage返回false,循环停止,同时应用程序终止。

    消息处理:DispatchMessage()把取出来的消息分配给相应的窗口或线程,由窗口过程处理函数DefWindowProc()处理。

    ==============================================================================================================================================================================割割割割割

    以上简要地介绍了消息队列,消息循环与消息处理的概念。

    Windows的应用程序靠消息驱动来实现功能。而消息驱动靠消息机制来处理。消息机制就是由消息队列,消息循环,消息处理构成的。

    那么,消息机制是如何运作的呢?

    当用户运行一个应用程序,通过对鼠标的点击或键盘按键,产生一些特定事件。由于Windows一直监控着I/O设备,该事件首先会被翻译成消息,由系统捕获,存放于系统消息队列。经分析,Windows知道该消息应由那个应用程序处理,则拷贝到相应的应用程序消息队列。由于消息循环不断检索自身的消息队列,当发现应用程序消息队列里有消息,就用GetMessage()取出消息,封装成Msg()结构。如果该消息是由键盘按键产生的,用TranslateMessage()翻译为WM_CHAR消息,否则,用DisPatchMessage()将取出的消息分发到相应的应用程序窗口,交由窗口处理程序处理。Windows为每个窗体预留了过程窗口函数,该函数是一个回掉函数,由系统调用应用程序不能调用。程序员可以通过重载该函数处理我们”感兴趣”的消息。对于不感兴趣的消息,则由系统默认的窗口过程处理程序做出处理。

    下面看这么一张图:

     

    这张图很好地解释了消息机制的运行原理。 

    当运行程序->事件操作引发消息->消息先存在系统消息队列->再存入到应用程序消息队列->用消息循环提取消息->处理消息->再返回消息队列....

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    } 
    

     上面代码的执行过程为:
    1. 消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。
    2. 事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。
    3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。
    4. 上面的步骤执行完后,将消息传递给DispatchMessage()函数。DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。
    5. 在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。
    6. 一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。

  • 相关阅读:
    JS转义 escape()、encodeURI()、encodeURIComponent()区别详解
    PHP解决搜索时在URL地址栏输入中文字符搜索结果出现乱码
    CMSPRESS-PHP无限级分类2
    CMSPRESS-PHP无限级分类
    HTML5-CSS3-JavaScript(3)
    HTML5-CSS3-JavaScript(2)
    HTML5-CSS3-JavaScript(1)
    CSS3-Hover 效果 展示
    JAVA Socket地址绑定
    JAVA Socket无参构造方法的使用
  • 原文地址:https://www.cnblogs.com/yskn/p/9677526.html
Copyright © 2020-2023  润新知