一,消息
消息(Message)指的就是Windows 操作系统发给应用程序的一个通知,它告诉应用程序某个特定的事件发生了。比如,用户单击鼠标或按键都会引发Windows 系统发送相应的消息。最终处理消息的是应用程序的窗口函数,如果程序没处理的话操作系统有默认函数将会作出处理。
从数据结构的角度来说,消息是一个结构体,它包含了消息的类型标识符以及其他的一些附加信息。系统定义的结构体MSG用于表示消息,MSG 具有如下定义形式:
typedef struct MSG
{
HWND hwnd; //hwnd 是窗口的句柄,这个参数将决定由哪个窗口过程函数对消息进行处理
UINT message; //message是一个消息常量,用来表示消息的类型
WPARAM wParam; //32 位的附加信息,具体表示什么内容,要视消息的类型而定
LPARAM lParam; //32 位的附加信息,具体表示什么内容,要视消息的类型而定
DWORD time; //time 是消息发送的时间
POINT pt; //消息发送时鼠标所在的位置
}
二,Windows编程原理
Windows 是一消息(Message)驱动式系统,Windows 消息提供了应用程序与应用程序之间、应用程序与Windows 系统之间进行通讯的手段。应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成。Windows 系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由 Windows 监控,当一个事件发生时,Windows 先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。
箭头1 说明操作系统能够操纵输入输出设备,例如让打印机打印;
箭头2 说明操作系统能够感知输入输出设备的状态变化,如鼠标单击,按键按下等,这就是操作系统和计算机硬件之间的交互关系
箭头3 是应用程序通知操作系统执行某个具体的操作,这是通过调用操作系统的API 来实现的;
箭头4 操作系统能够感知硬件的状态变化,但是并不决定如何处理,而是把这种变化封装成消息转交给应用程序,由应用程序决定如何处理,箭头4说明了这种转交情况。
三,Windows消息循环
消息循环是Windows 应用程序存在的根本,应用程序通过消息循环获取各种消息,并通过相应的窗口过程函数,对消息加以处理;正是这个消息循环使得一个应用程序能够响应外部的各种事件。
Windows 操作系统为每个线程维持一个消息队列,当事件产生时,操作系统感知这一事件的发生,并包装成消息发送到消息队列,应用程序通过GetMessage()函数取得消息并存于一个消息结构体中,然后通过一个TranslateMessage()和DispatchMessage()解释和分发消息,下面的代码描述了Windows 的消息循环。
while(GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
TranslateMessage(&msg)对于大多数消息而言不起作用,但是有些消息,比如键盘按键按下和弹起(分别对于KeyDown 和KeyUp 消息),却需要通过它解释,产生一个WM_CHAR消息。DispatchMessage(&msg)负责把消息分发到消息结构体中对应的窗口,交由窗口过程函数处理。GetMessage()在取得WM_QUIT 之前的返回值都为TRUE,也就是说只有获取到WM_QUIT 消息才返回FALSE,才能跳出消息循环。
对一个Windows窗体程序而言,在Program.cs文件中的Main函数中,有如下的代码:
Application.Run(new Form1());
这行代码的意思就是在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。实际上就是启动了一个GetMessage的无限循环。而这个响应Windows消息的线程就被称做Windows窗体程序的UI线程
四,主要函数的区别
SendMessage()与PostMessage()是用于向应用程序发送消息的。SendMessage()将消息直接加入到应用程序的消息队列中,在应用程序处理完此消息后,它才返回。PostMessagex()将消息直接加入到应用程序的消息队列中,不等程序返回就退出。
PeekMessage和GetMessage用来从消息队列中取出数据,GetMessage从消息队列里取得一个消息并将其放于指定的结构,获取消息成功后,线程将从消息队列中删除该消息。GetMessage函数会一直等待直到有消息到来才有返回值。PeekMessage函数检查消息队列,并将该消息(如果存在)放于指定的结构,然后返回,不会等待。