zoukankan      html  css  js  c++  java
  • Win32消息机制

    1、 消息机制
         过程驱动:程序是按照我们预先定义好的顺序执行,每执行一步,下一步都已经按照预定的顺序继续执行,直到程序结束。
          
       事件驱动:程序的执行顺序是无序的。某个时间点所执行的代码,是由外界通知。由于我们无法决定用户执行顺序,所以代码的执行也是无序。
          
           Win32的消息机制 - 事件驱动

    2、 Win32消息程序

      2.1、Win32消息循环

        2.1.1、GetMessasge

          BOOL GetMessage(LPMSG lpMsg,//存放获取到的消息数据
                     HWND hWnd,//获取消息的窗口句柄
                     UINT wMsgFilterMin,//消息过滤的起始消息
                     UINT wMsgFilterMax //消息过滤的终止消息
           );

          MSG - 由系统填写关于消息的参数
            hWnd- GetMessage会根据hWnd值,接收由hWnd指定的窗口的消息。
            wMsgFilterMin,wMsgFilterMax - 消息过滤器,要求GetMessage接收指定范围的消息。

          返回值BOOL:成功获取消息,返回TRUE,但是当获取到WM_QUIT消息时,返回FALSE。
            可以使用PostQuitMessage向窗口发送WM_QUIT消息

        2.1.2 TranslateMessage
            就是将键盘消息转换成字符消息。
            1 首先检查是否是键盘按键消息     
            2 如果发现是按键消息,将根据按键,产生一个字符消息,在下一个GetMessage执行时,会收到这个消息。
            3 如果未发现按键消息,不做任何处理。然后执行下一个函数

        2.1.3 DispatchMessage
            根据消息数据内窗口句柄,找到这个窗口的窗口处理函数, 调用处理函数,进行消息处理。
            如果MSG中,HWND窗口句柄为空,DispatchMessage不做任何处理。

      2.2、Win32基本消息

        2.2.1 WM_DESTROY
               窗口销毁时的消息,可以做退出或善后处理。
            2.2.2 WM_CREATE
               窗口创建消息,是在窗口创建后,窗口处理函数收到第一条消息。可以在这个消息内做 数据初始化/创建子窗口等。
               WPARAM wParam - 不使用
               LPARAM lParam - CREATESTRUCT指针
            2.2.3 WM_SIZE
               当窗口大小发生变化时,会收到这个消息。可以在这个消息中调整窗口布局。
               wParam - SIZE发生变化时的标识
           LOWORD(lParam); - 客户区的宽
               HIWORD(lParam); - 客户区的高
            2.2.4 WM_SYSCOMMAND
               系统命令消息,当点击系统菜单和按钮时,会收到。可以在这个消息中,提示用户保存数据等。
               wParam - 系统命令类型
           LOWORD(lParam) - 屏幕X坐标
           HIWORD(lParam) - 屏幕Y坐标

      2.3 MSG - 消息结构

        typedef struct tagMSG {  HWND   hwnd; //消息的窗口句柄  
                       UINT   message;//消息标示
                       WPARAM wParam; //消息的参数,32位
                       LPARAM lParam; //消息的参数,32位
                       DWORD  time;//消息产生的时间
                       POINT  pt; //消息产生时,鼠标的位置
         } MSG;

      2.4 消息的获取和发送

        2.4.1 获取GetMessage/PeekMessage
              GetMessage 获取消息,阻塞函数
              PeekMessage 获取消息,非阻塞函数,如果获取不到消息就直接向下执行,直到结束
          2.4.2 发送SendMessage/PostMessage
                SendMessage 发送消息并等候消息处理结束才返回。
              PostMessage 发送消息后立即返回,不关心消息处理的结果。
              LRESULT SendMessage/PostMessage( HWND hWnd,      //处理消息窗口
                                UINT Msg,       //消息的ID
                                WPARAM wParam,  //消息的参数
                                LPARAM lParam    //消息的参数

          );

    3  消息组成和分类

       3.1 消息组成
           窗口句柄/消息ID/消息参数(WPARAM.LPARAM)
         3.2 消息分类
             3.2.1 系统消息 - 由系统定义和使用的消息
                 例如:WM_CREATE/WM_SIZE
                 消息ID范围为: 0 - 0x03FF(WM_USER-1)
             3.2.2 用户定义消息 - 应用程序可以自己定义
                 和使用的消息, WM_USER(0x0400),从WM_USER的ID开始,到0x7FFF,是用户可以定义使用的消息.

             3.2.3 其他消息范围
                 WM_APP(0x8000)-0xBFFF:应用程序访问窗口的消息ID
                 0xC000-0xFFFF: 应用程序访问消息,使用字符串注册系统产生相应消息ID
             3.2.4 用户定义消息的使用
                 1)定义自定义消息ID:
                   #define   WM_FIRSTMSG  (WM_USER+1)
                 2)在窗口处理函数中,响应消息
                     switch( nMsg )
                {
                case WM_FIRSTMSG://处理函数
                break;
                     }
                 3)SendMessage/PostMessage发送消息
                    SendMessage( hWnd, WM_FIRSTMSG, 0, 0 );

    4 消息队列
          4.1 消息队列 - 用于存储消息的内存空间, 消息在队列中是先入先出.
          4.2 消息队列的分类
             4.2.1 系统消息队列 - 由系统维护的消息队列.
             4.2.2 应用程序消息队列(线程消息对列) -属于每个线程的各自拥有的消息队列.

    5、消息和消息队列    

        5.1 根据消息和消息队列关系,将消息分成两种:       队列消息 - 可以存放在消息队列中的消息.      

                                非队列消息 - 发送时不进入消息队列.

            5.2 队列消息,用PostMessage函数把队列消息投递到消息队列中,然后由消息处理函数DispatchMessage传给窗口处理函数。首先存放到消息队列当中,然后由GetMessage/PeekMessage取出,然后进行处理。

          例如: 鼠标消息/键盘消息/WM_PAINT/WM_QUIT          WM_TIMER消息

           5.3 非队列消息,用SendMessage()函数把非队列消息直接发送至窗口过程。消息发送直接发送给指定的窗口,查找窗口的处理函数,返回处理结果.  比如WM_CREATE  WM_SIZE  WM_SHOWWINDOW  WM_COMMAND  WM_DESTOY

      

      

    6、消息的获取      

        6.1 消息循环      

           6.1.1 GetMesssage从对列中获取消息,  判断是否是WM_QUIT消息,如果发现是WM_QUIT消息,消息循环结束,否则继续下一步。

               6.1.2 TranslateMessage 翻译按键消息,  如果发现有按键消息,产生字符消息放入消息对列, 继续下一步      

           6.1.3 DispatchMessage 找到消息所发窗口的处理函数,处理消息.处理完成后, 返回6.1.1.

           6.2 GetMesssage和PeekMessage     

            6.2.1 从线程消息队列中获取消息,如果找到消息,就返回消息,进行消息处理. 如果未找到消息,执行6.2.2     

            6.2.2 查找系统消息队列.通过向系统消息队列查询,如果找到消息,获取消息并返回,进行消息处理.如果未找到消息,执行6.2.3   

              6.2.3 检查窗口需要重新绘制的范围,如果发现存在重新绘制的范围,会产生WM_PAINT消息。然后进行消息处理, 如果未找,执行6.2.4   

              6.2.4 检查WM_TIMER定时器消息,如果发现存在已经到时的定时器,会产生WM_TIMER消息。然后进行消息处理. 如果未找,执行6.2.5  

              6.2.5 执行内存管理工作.

                6.2.6 根据函数不同,处理结果不同:GetMesssage - 阻塞,等候下一条消息    

                                PeekMessage - 让出控制权,交给后面的代码执行。

    7 消息发送 
          7.1 消息发送分两种
               发送(Send)消息 - 直接发送给指定的窗口,并等候结果。
               投递(Post)消息 - 发送到消息队列当中,立刻返回,由消息循环处理。
          7.2 PostMessage和SendMessage
                PostMessage产生队列消息,由于发送后不等候消息处理结果,所以不能确定消息是否被处理成功。
                SendMessage产生非队列消息,可以确定消息是否成功。       

  • 相关阅读:
    CodeForces 7B
    CodeForces 4D
    离散化
    线段树入门
    洛谷 P3951 小凯的疑惑(赛瓦维斯特定理)
    Codeforces 1295D Same GCDs (欧拉函数)
    Codeforces 1295C Obtain The String (二分)
    Codeforces 1295B Infinite Prefixes
    Codeforces 1295A Display The Number(思维)
    Codeforces 1294F Three Paths on a Tree(树的直径,思维)
  • 原文地址:https://www.cnblogs.com/zjzsky/p/3471701.html
Copyright © 2011-2022 走看看