zoukankan      html  css  js  c++  java
  • MSG结构体和WndProc窗口过程详解

    MSG结构体和WndProc窗口过程对于Windows编程非常重要,如果不了解它们,可以说就没有学会Windows编程。

    MSG结构体

    MSG 结构体用来表示一条消息,各个字段的含义如下:

    1. typedef struct tagMSG{
    2. HWND hwnd; //窗口句柄
    3. UINT message; //消息类型
    4. WPARAM wParam; //附加消息1
    5. LPARAM lParam; //附加消息2
    6. DWORD time; //消息被传递时候的时间
    7. POINT pt; //消息被传递时光标在屏幕上的位置
    8. } MSG;

    对各个字段的说明:
    1) 最后两个字段 time 和 pt 一般由系统使用,我们很少用到。

    2) message 为消息类型,也就是以 WM 开头的消息(WM 是 Window Message 的缩写 ),例如 WM_CREATE、WM_PAINT、WM_DESTROY、WM_COMMAND 等。

    2) wParam 和 lParam 是要重点说明的,它们都表示附加消息。例如,当收到一个字符消息的时,message 的值为 WM_CHAR,但用户到底输入的是什么字符,那么就由 wParam 和 lParam 来说明。wParam、lParam 表示的信息随消息类型的不同而不同,具体细节可以到MSDN中查看。

    WPARAM 和 LPARAM 这两种数据类型的定义分别为:

    typedef  UINT_PTR  WPARAM;
    typedef  LONG_PTR  LPARAM;

    在现代操作系统中(32位和64位操作系统),它们一般都表示 32 位的整数。

    但在16位操作系统中,WPARAM 表示16位整数,而 LPARAM 表示32位整数,根据匈牙利命名法,16 位的变量通常以W开头,32 位变量通常以L开头。升级到32位操作系统后,WPARAM也被扩展到32位,此时 WPARAM 和 LPARAM 的大小完全相同。

    在 Win32 API 的早期,由于还有很多 Win16 API 的软件,为了保证和 Win16 API 的代码可移植性,微软依然保留了 WPARAM 和 LPARAM 两个宏。

    不过16位系统早已成为历史,现在你可以认为这两个参数的长度相同。读者可以在 VC / VS 中通过 F12 键或者“转到定义”菜单查看。

    wParam 和 lParam 到底表示什么信息

    可以肯定的是,消息类型 message 不同,wParam 和 lParam 两个字段表示的附加消息一般也不同。那么,它们到底表示什么呢?其实这个真的不一定,没有什么规律,它们本来就是一个历史遗留问题,也不知道微软到底怎么安排的,只能根据不同的消息类型去 MSDN 中查找。

    一般约定,wParam 用来表示控件的ID,或者高 16 位和低 16 位组合起来分别表示鼠标的位置,如果发送消息时需要附带某种结构的指针或者是某种类型的句柄时,习惯上用 lParam。

    不过这也不一定是对的,例如对于一个鼠标左键按下的消息 WM_LBUTTONDOW,就用 lParam 来表示鼠标的坐标:

    1. //point 是一个结构体,表示鼠标坐标
    2. //msg 表示一条消息
    3. point.x = LOWORD( msg.lParam );
    4. point.y = HIWORD( msg.lParam );

    LOWORD 和 HIWORD 都是宏定义:LOWORD 用来取一个 32 位数的低 16 位,HIWORD 用来取一个32 位数的高 16 位。对于 WM_LBUTTONDOW 消息,低 16 位存放的是 x 坐标,而高 16 位存放的是 y 坐标。

    WndProc 窗口过程

    窗口过程一般定义为如下的形式:

    1. LRESULT CALLBACK WndProc(
    2. HWND hwnd, //窗口句柄
    3. UINT message, //消息类型
    4. WPARAM wParam, //附加消息1
    5. LPARAM lParam //附加消息2
    6. ){
    7. // TODO
    8. }

    WndProc 的各个参数和 MSG 结构体的前四个字段是一一对应的。需要铭记的是:每产生一条消息,都会调用一次 WndProc 函数。

    当用户点击按钮、编辑框、下拉列表框等控件的时候,会产生WM_COMMAND消息。对于不同来源的 WM_COMMAND 消息,wParam、lParam 参数也不同,见下表:

    消息来源wParam (高16位)wParam (低16位)lParam
    菜单 0 菜单ID 0
    快捷键 1 快捷键ID 0
    控件 控件通知码 控件ID 控件句柄


    注意:

    • 上面说的菜单是指窗口标题下方、客户区上方的下拉菜单,而不是客户区的下拉列表框控件。
    • 控件通知码用来识别控件的操作。例如 Button 控件一般有两种通知码,BN_CLICKED 和 BN_DOUBLECLICKED,前者表示 Button 被单击,后者表示 Button 被双击。


    对于 Button 控件,我们可以通过LOWORD(wParam)来获取它的 ID,这就是上节最后一个例子的原理,请参考上节的代码体会。

  • 相关阅读:
    VSCode打开大文件插件
    https Java SSL Exception protocol_version
    Error creating bean with name 'tomcatEmbeddedServletContainerFactory ' (or a BeanPostProcessor involved) returned null
    在Java8的foreach()中不能break,如果需要continue时,可以使用return
    Spring cloud 超时及重试配置【ribbon及其它http client】
    祸害阿里云宕机 3 小时的 IO HANG 究竟是个什么鬼?!
    Convertion of grey code and binary 格雷码和二进制数之间的转换
    stringstream 使用方法
    [LeetCode] 91. Decode Ways 解码方法
    QString, string, int, char* 之间相互转换
  • 原文地址:https://www.cnblogs.com/ganbing/p/6281895.html
Copyright © 2011-2022 走看看