消息机制的相关信息

消息机制
   1 程序的执行机制
     过程驱动 - 程序的执行过程按照事先安排好的顺序执行。
 
     事件驱动 - 程序的执行是无序的,用户可以根据需要随机触发相应的事件。
 
     WIN32 窗口程序 采用的 事件驱动 方式 也就是消息机制。
 
   2 消息机制
     2.1 消息的定义
       每个消息都有一个ID, 同时还附带两个消息的参数
  
typedef struct tagMSG {
   HWND   hwnd;//窗口句柄。     
   UINT   message; //消息的ID
   WPARAM wParam;  //消息附加参数1
   LPARAM lParam;  //消息附加参数2
   DWORD  time; //消息产生的时间。
   POINT  pt; //消息产生时鼠标的位置
} MSG; 
     2.2 窗口处理函数
       每个窗口必须都有窗口处理函数。
LRESULT CALLBACK WindowProc(
 HWND hwnd,      // 窗口句柄
 UINT uMsg,      // 消息ID
 WPARAM wParam,  // 消息附加参数1
 LPARAM lParam   // 消息附加参数2
);
当系统通知窗口时,会调用窗口处理函数,
同时将消息的ID和参数传递给窗口处理函
数。
在窗口处理函数中,不处理的消息调用缺省
处理函数 DefWindowProc
WINAPI/APIENTRY/CALLBACK回调,自定义给win操作系统调用的函数 必须交给__stdcall声明,仅C++编译器
     2.3 消息相关的函数
        2.3.1 GetMessage - 提取消息
BOOL GetMessage(
 LPMSG lpMsg,         
 // 获取到的消息的BUFF
 HWND hWnd,           
 // 窗口句柄(指定获取哪个窗口的消息)
 UINT wMsgFilterMin,  
 // 获取消息最小ID
 UINT wMsgFilterMax   
 // 获取消息最大ID
);
        wMsgFilterMin和wMsgFilterMax只能获取
由这两个值,指定的消息的范围,如果都
为0,表示没有范围。
        
2.3.2 TranslateMessage - 翻译消息
 将按键消息(不包括不可见字符的按键
 消息),翻译成字符消息。
BOOL TranslateMessage(
 CONST MSG *lpMsg   
 // 要翻译的消息的地址
);
          首先检查是否是可见字符按键消息,如果
 不是,直接返回。
2.3.3 DispatchMessage - 派发消息
 将消息派发到消息对应的窗口处理函数中
          LONG DispatchMessage(
 获取nMsg.hWnd,根据这个窗口句柄,获取存储窗口数据的内存 从内存中获取
 窗口类名"Wnd"根据这个"Wnd"到操作系统中匹配窗口类 
 一旦匹配成功,调用这个窗口类中的窗口处理函数
 CONST MSG *lpmsg   
 // 准备派发的消息的地址
 );
   3 常见几个消息
消息何时产生
消息有何操作
消息附带信息
     3.1 WM_DESTROY - 窗口销毁时的消息。
           无消息参数,常用于窗口销毁之前的
  善后处理,例如:资源,内存的回收等
     3.2 WM_SYSCOMMAND - 系统命令消息。
           当点击 最大化/最小化/关闭按钮等命令
  时,收到消息。
  常用于窗口关闭时提示用户处理。
           LPARAM 
     LOWORD - 鼠标的X轴坐标
     HIWORD - 鼠标的Y轴坐标
  WPARAM - 具体的命令,例如:SC_CLOSE  
     3.3 WM_CREATE - 窗口创建成功但还未显示之前
            常用于窗口的参数初始化,资源创建
   包括子窗口的创建。
   WPARAM - 不使用
   LPARAM - 是CREATESTRUCT结构体的指针
            保存了CreateWindowEx函数的
    12个参数
     3.4 WM_SIZE - 窗口的大小发生变化后,收到
                   这个消息。
            常用于窗口大小变化后,调整窗口内的布局。

   WPARAM - 窗口大小变化的原因
   LPARAM
     LOWORD - 窗口大小变化后客户区的
              宽度
              HIWORD - 窗口大小变化后客户区的
              高度
     3.5 WM_QUIT - 用于结束消息循环。
            WPARAM - 退出码 PostQuitMessage函数
                的参数指定。
            LPARAM - 不使用。
当GetMessage收到这个消息后,会返回
FALSE,结束while处理,退出消息循环
     3.6 WM_PAINT - 绘图消息
     3.7 键盘消息
     3.8 鼠标消息
     3.9 定时器消息
   4 消息的获取和发送
     4.1 消息的获取
        GetMessage - 从系统中获取消息,将消息从
           系统中移除,阻塞函数,当系
   统中没有消息,这个函数阻塞
   等候下一条消息。
        PeekMessage - 以查看的方式从系统中获取
           消息,可以不将消息移除,非
   阻塞函数。
BOOL PeekMessage(
 LPMSG lpMsg, //
 HWND hWnd,   //
 UINT wMsgFilterMin,  //
 UINT wMsgFilterMax,  // 
 UINT wRemoveMsg      
 // 移除标识
);
     4.2 消息的发送
       PostMessage/SendMessage
BOOL PostMessage(
 HWND hWnd,      
 // 窗口句柄,确定哪一个窗口的处理函数来处理这个消息
 UINT Msg,       
 // 消息ID
 WPARAM wParam,  
 // 消息参数1
 LPARAM lParam   
 // 消息参数2
);
LRESULT SendMessage(
 HWND hWnd,      
 UINT Msg,       
 WPARAM wParam,  
 LPARAM lParam   
);
PostMessage - 投递消息,消息发出后立刻
    返回,不等候消息的处理结果。
        SendMessage - 发送消息,消息发出后,等
    候消息处理完,才返回。


一 消息的作用和组成
   1 消息的作用
     当系统通知窗口工作时,以消息的方式,派发给
     窗口。
   2 消息组成
     窗口句柄
     消息ID
     消息附带参数1和2(wParam, lParam)
     -------以上4个直接传给窗口处理函数------
     消息的产生时间
     消息产生时光标位置
     ---后2个可通过函数得到 
        消息的产生时间由GetMessageTime函数得到
        消息产生时光标位置GetMessagePos函数得到
二 消息的分类
   1 系统消息 - ID范围(0-0x03FF)1024个
     由系统定义好的消息,所有程序直接可以使用
   2 用户自定义消息 - ID范围(0x0400-0x7FFF)
     由用户自己定义,满足用户自己的需要,用户
     自定义的消息,需要用户自己发送,并负责处
     理。
       定义宏 WM_USER 代表0x400,自定义消息ID时
       #define WM_MYMESSAGE WM_USER+n 
   3 应用程序消息 - ID范围(0x8000-0xBFFF)
     用于程序之间的通信(目前用不到)
       定义宏 WM_APP 代表0x8000
   4 系统注册消息 - ID范围(0xC000-0xFFFF)
     在系统注册并生成消息,然后在各个应用程序
     中使用。
三 消息和消息队列
   1 消息队列
     用于存放消息的队列,消息在队列中先进先出,
     所有窗口都有消息队列,程序从消息队列中提
     取消息。
   2 消息队列的类型
     2.1 系统消息队列
        由系统维护的消息队列,存放系统产生的消
息。(鼠标,键盘等)
     2.2 程序消息队列
        属于程序(线程)的消息队列,由程序本身
负责维护。
   3 消息队列的关系
     3.1 当鼠标和键盘产生消息时,先放入系统
     消息队列。
     3.2 系统会根据存放消息,找到对应的窗口
     信息。
     3.3 按照对应窗口信息,将消息转发给相应
     的程序消息队列中。
   4 消息和消息队列
     4.1 根据消息和消息队列的使用关系
        4.1.1 队列消息
 将消息存入消息队列,消息的发送和获取
 都是通过队列完成的。
4.1.2 非队列消息
 消息不进入队列,直接调用窗口处理函数
     4.2 队列消息 - 先把消息放入队列,通过消息
                  循环从队列中取得消息并且发送
 给窗口处理函数。
           GetMessage/PeekMessage - 取队列消息
  PostMessage - 向队列中投递消息
     4.3 非队列消息 - 消息直接找 对应的窗口处
                  理函数,并调用处理函数,完成
 处理。
           SendMessage - 发送非队列消息,直接
         窗口处理函数,等待处理结果。(对时间要求严格的才用)
 WM_CREATE
 WM_SIZE
   5 消息的获取
     5.1 消息循环
       5.1.1 GetMessage/PeekMessage 从程序的消息
             队列中获取消息
       5.1.2 TranslateMessage - 检查GetMessage
             函数获取到的消息,如果是可见字符
    按键消息,产生一个字符消息
    (WM_CHAR),并且将字符消息放入消息
    队列。
       5.1.3 DispatchMessage - 根据取出的消息,
             找到对应的窗口处理函数,完成消息
    的处理
     5.2 GetMessage/PeekMessage执行机制
        1 先去程序(线程)的消息队列中检查有没有
 消息,如果有消息,检查指定条件
 (窗口句柄,ID范围)是否满足,如果满足
 条件取出消息进行处理。
        2 如果程序(线程)的消息队列中没有消息
 向系统的消息队列中 获取 本程序的消息
 ,系统将消息转发给 程序的消息队列,
 然后GetMessage/PeekMessage再从程序的
 消息队列中获取消息。
 (系统队列中的消息无法直接获取,需要
   转发到程序的消息队列中再获取)
        3 如果系统的消息队列中也没有和本程序相
 关的消息,检查 有没有 需要重新绘制的
 区域,如果有 发送 WM_PAINT 消息,放入
 队列,取出并处理。
        4 如果没有 需要重新绘制的区域,检查有
 没有到时间的定时器,如果有 发送
 WM_TIMER 消息,放入队列,取出并处理。
        5 如果以上都没有,整理内存和资源等。
6 GetMessage 阻塞等候下一条消息,
 PeekMessage 会返回FALSE,交出程序的
 控制权。


 注:GetMessage 函数 如果获取到WM_QUIT
     返回0


   6 消息发送
     SendMessage - 直接将消息发送到窗口处理函数
                   ,等待处理结果(非队列消息)
     PostMessage - 将消息放入队列,立即返回,
                   消息 由 消息循环 从消息队列
  中取出,并负责处理(队列消息)
四 WM_PAINT
  1 WM_PAINT - 窗口中 有 需要重新绘制的区域,
               GetMessage函数就会发送 WM_PAINT 消息
    窗口需要重新绘制的区域叫做 窗口无效区域
    UpdateWindow/RedrawWindow刷新整个窗口
被声明称需要重新绘制的区域
    BOOL InvalidateRect(
 HWND hWnd,  // 窗口句柄
 CONST RECT *lpRect,
// 定义无效区域(可以为NULL)
 BOOL bErase // 擦除标识
);
  2 绘图步骤(WM_PAINT)
    2.1 BeginPaint - 开始绘图
     HDC BeginPaint(
 HWND hwnd, 
 // 窗口句柄
 LPPAINTSTRUCT lpPaint
 // 绘图结构体的指针(程序员基本不用)
);//返回绘图设备句柄
    2.2 绘图(需要使用到HDC) 
    2.3 EndPaint - 结束绘图
BOOL EndPaint(
 HWND hWnd,  // 窗口句柄
 CONST PAINTSTRUCT *lpPaint 
 // 绘图结构体的指针(程序员基本不用)
);
      WM_PAINT的处理过程:
        如果有无效区域(无效区域标识),在合适
的时机 产生WM_PAINT消息,在处理函数中
对这个消息进行处理,处理时 先调用
BeginPaint(),得到绘图设备句柄的同时去
掉无效区域标识,然后 用HDC 完成绘图,
最后利用EndPaint结束绘图。
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
day04
五 键盘消息
   1 键盘消息
     WM_KEYDOWN - 按键按下时产生的消息
     WM_KEYUP - 按键被放开时产生的消息
       WPARAM - 虚拟键码
       LPARAM - 按键的参数,比如 按键的次数等
     WM_CHAR - 字符消息(TranslateMessage)
       WPARAM - 字符编码
       LPARAM - 按键的参数
     WM_SYSKEYDOWN - 系统按键被按下(ALT/F10)
     WM_SYSKEYUP - 系统按键被放开
       WPARAM - 虚拟键码,如果不是
       LPARAM - 按键的参数,比如 按键的次数等
   2 消息特性
     2.1 WM_KEYDOWN 可以重复出现,WM_KEYUP
         只能在松开时出现一次。
     2.2 TranslateMessage函数可以转换WM_KEYDOWN
         消息,在转换时对于可见字符按键(先判断CapsLock键是否打开,aA为例
如果CapsLock键打开用PostMessage(nMsg.hWnd,WM_CHAR,0x41,..)
CapsLock键没有打开用PostMessage(nMsg.hWnd,WM_CHAR,0x61,..))转换成
WM_CHAR,对于不可见字符不予转换,直接return
(字符消息是转换来得,不是按下的)
     2.3 按键消息的WPARAM 表示按键的虚拟键码,
         字符消息的WPARAM 表示的是输入的字符(ASCII码)
(字符编码)。
六 鼠标消息
  1 鼠标基本消息
    鼠标左键按下 - WM_LBUTTONDOWN
    鼠标左键弹起 - WM_LBUTTONUP
    鼠标右键按下 - WM_RBUTTONDOWN
    鼠标右键弹起 - WM_RBUTTONUP
    鼠标移动 - WM_MOUSEMOVE
      WPARAM - 按键的状态
      LPARAM
        LOWORD - 鼠标光标的X轴坐标
HIWORD - 鼠标光标的Y轴坐标
  2 双击消息
    鼠标左键双击 - WM_LBUTTONDBLCLK
    鼠标右键双击 - WM_RBUTTONDBLCLK
      WPARAM - 按键的状态
      LPARAM
        LOWORD - 鼠标光标的X轴坐标
HIWORD - 鼠标光标的Y轴坐标
  3 鼠标滚轮消息 - WM_MOUSEWHEEL
      WPARAM 
        LOWORD - 按键状态
HIWORD - 滚轮滚动偏移量(120倍数)
  正数代表向前滚,负数代表向后滚
      LPARAM
        LOWORD - 鼠标光标的X轴坐标
HIWORD - 鼠标光标的Y轴坐标
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值