消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对单击鼠标所产生的消息来说,这个记录(结构体)中包含了单击鼠标的消息号(WM_LBUTTONDOWN)、单击鼠标时的坐标(由X,Y值连接而成的一个32位整数)。这个记录类型叫做MSG。
typedef struct tagMSG
{
HWND hwnd;/ /窗口句柄
UINT message;//消息常量标识符
WPARAM wParam;// 16位消息的特定附加信息
LPARAM lParam;// 32位消息的特定附加信息
DWORD time;/ /消息创建时的时间
POINT pt;/ /消息创建时的鼠标位置
} MSG;
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT;
hwnd
32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。
message
用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。
wParam
通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。
lParam
通常是一个指向内存中数据的指针。
由于WParam、lParam和Pointer都是32位的,即等同于DWORD。因此,它们之间可以相互转换。
Windows的消息系统是由3个部分组成的:
·消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取
消息,然后分派给某个窗口。
后继续从
消息队列中检索下一条消息,再分派给适当的窗口,依次进行。
· 窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后
响应它。窗口过程是一个
回调函数;处理了一个消息后,它通常要返回一个值给Windows。
注意
回调函数是程序中的一种函数,它是由Windows或外部模块调用的。
一个消息从产生到被一个窗口响应,其中有5个步骤:
1) 系统中发生了某个事件。
2) Windows把这个事件翻译为消息,然后把它放到
消息队列中。
4)
应用程序把消息传递给一个适当的窗口的窗口过程。
5) 窗口过程响应这个消息并进行处理。
步骤3和4构成了
应用程序的
消息循环。
消息循环往往是Windows
应用程序的核心,因为消息循环使一个
应用程序能够响应外部的事件。
消息循环的任务就是从
消息队列中检索消息,然后把消息传递给适当的窗口。如果
消息队列中没有消息,Windows就允许其他
应用程序处理它们的消息。
Windows消息控制中心一般是
三层结构,其顶端就是Windows内核。Windows内核维护着一个
消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级
窗体(Window)或控件(Control)。第二级控制中心一般是各Windows
应用程序的Application对象。第三级控制中心就是Windows
窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息。
Windows
操作系统中包括以下几种消息:
1、标准Windows消息:
这种消息以WM_打头。
2、通知消息
通知消息是针对标准Windows控件的消息。这些控件包括:按钮(Button)、
组合框(ComboBox)、编辑框(TextBox)、列表框(ListBox)、
ListView控件、Treeview控件、
工具条(Toolbar)、
菜单(Menu)等。每种消息以不同的字符串打头。
3、自定义消息
消息传送
1、从
消息队列获取消息:
2、发送消息
发送消息到指定
窗体一般通过以下两个函数完成:SendMessage和PostMessage。两个函数的区别在于:PostMessage函数只是向线程
消息队列中添加消息,如果添加成功,则返回True,否则返回False,消息是否被处理,或处理的结果,就不知道了。而SendMessage则有些不同,它并不是把消息加入到队列里,而是直接翻译消息和调用消息处理(线程向自己发送消息才是这样),直到消息处理完成后才返回。所以,如果我们希望发送的消息立即被执行,就应该调用SendMessage。
还有一点,就是SendMessage发送的消息由于不会被加入到
消息队列中(错:线程向其他线程发送消息也是追加到其他线程的发送消息队列的,即使这两个线程在同一个进程也是如此),所以通过PeekMessage或GetMessage是不能获取到由SendMessage发送的消息。
另外,有些消息用PostMessage不会成功,比如wm_settext。所以不是所有的消息都能够用PostMessage的。