MSG 消息结构体和WndProc 窗口过程

MSG 消息结构体原型:

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

MSG Structure1 | Microsoft Docs

https://docs.microsoft.com/en-us/previous-versions/900ks98t(v=vs.140)

字段说明:

第一个成员变量hwnd表示消息所属的窗口。我们通常开发的程序都是窗口应用程序,一个消息一般都是与某个窗口相关联的。例如,在某个活动窗口中按下鼠标左键,产生的按键消息就是发给该窗口的。在Windows程序中,用HWND类型的变量来标识窗口。

第二个成员变量message指定了消息的标识符。在Windows中,消息是由一个数值来表示的,不同的消息对应不同的数值。但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM是Window Message的缩写)的形式,XXX对应某种消息的英文拼写的大写形式。例如,鼠标左键按下消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN,字符消息是WM_CHAR,等等。在程序中我们通常都是以WM_XXX宏的形式来使用消息的。
提示:如果想知道WM_XXX消息对应的具体数值,可以在Visual C++开发环境中选中WM_XXX,然后单击鼠标右键,在弹出菜单中选择goto definition,即可看到该宏的具体定义。跟踪或查看某个变量的定义,都可以使用这个方法。

第三、第四个成员变量wParam和lParam,用于指定消息的附加信息。例如,当我们收到一个字符消息的时候,message成员变量的值就是WM_CHAR,但用户到底输入的是什么字符,那么就由wParam和lParam来说明。wParam、lParam表示的信息随消息的不同而不同。如果想知道这两个成员变量具体表示的信息,可以在MSDN中关于某个具体消息的说明文档查看到。读者可以在VC++的开发环境中通过goto definition查看一下WPARAM和LPARAM这两种类型的定义,可以发现这两种类型实际上就是unsigned int和long。

最后两个变量分别表示消息投递到消息队列中的时间和鼠标的当前位置。

在现代操作系统中(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 坐标。

一个消息由该消息所属的窗口hwnd、消息编号message、消息的WPARAM型参数wParam连同消息的LPARAM型参数lParam组成。消息的两个参数中包含了重要的内容。比如,对鼠标消息而言,lParam中一般包含鼠标的位置信息,而 wParam参数中则包含发生该消息时,对应的SHIFT键的状态信息等。对其他不同的消息类型来讲,wParam和 lParam也具备明确的定义。当然,用户也能够自定义消息,并定义消息的 wParam和 lParam意义。为了用户能够自定义消息,MiniGUI 定义了MSG_USER 宏,可如下定义自己的消息:

 #define MSG_MYMESSAGE1 (MSG_USER + 1)
 #define MSG_MYMESSAGE2 (MSG_USER + 2)

WndProc 窗口过程

Wndproc是Windows操作系统向应用程序发送一系列消息之一,每个窗口会有一个窗口过程的回调函数,分别是窗口句柄、消息ID、WPARAM、LPARAM。
WndProc 窗口过程

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

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.


发布日期:

所属分类: 编程 标签:


没有相关文章!