Windows API学习-MSG结构体和窗口过程详解(1)

几点说明
API.png

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

MSG结构体

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

typedef struct tagMSG{
    HWND hwnd;  //窗口句柄
    UINT message;  //消息类型
    WPARAM wParam;  //附加消息1
    LPARAM lParam;  //附加消息2
    DWORD time;  //消息被传递时候的时间
    POINT  pt;  //消息被传递时光标在屏幕上的位置
} 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 来表示鼠标的坐标:

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

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