Windows 消息机制 编写Windows程序有两年了,但当别人问起Windows消息机制总觉得很难形容清楚。在这篇中,集合了很多我从网络中搜集来的一些知识,这里只是汇总一下。 我们编写的Windows程序是以事件为驱动,消息机制为基础的。对于每一个正在执行的Windows应用程序,Windows为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。 一、消息循环
首先我们来看一下Windows消息循环。 while(GetMessage (&msg, NULL, 0, 0)) MSG结构在头文件中定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG;
其数据成员的具体意义如下: hwnd:消息将要发送到的那个窗口的句柄,用这个参数可以决定让哪个窗口接收消息。 message:消息号,它唯一标识了一种消息类型。每种消息类型都在Windows文件进行了预定义。 wParam:一个32位的消息参数,这个值的确切意义取决于消息本身。 lParam:同上。 time:消息放入消息队列中的时间,在这个域中写入的并非当时日期,而是从Windows启动后所测量的时间值。Windows用这个域来使用消息保持正确的顺序。 pt:消息放入消息队列时的鼠标坐标。 消息循环以GetMessage调用开始,它从消息队列中取出一个消息。然后解释和分发消息。 二、消息类型
消息主要分为两种:一是系统定义消息;二是自定义消息。 1、系统定义消息(System-Defined Messages) 在SDK中事先定义好的消息,非用户定义的,其范围在[0x0000, 0x03ff]之间, 可以分为以下三类: 2、 程序定义消息(Application-Defined Messages) 三、队列化消息和非队列化消息
消息被分成队列化消息和非队列化消息。 队列化消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化消息是在Windows的窗口过程中直接发送给窗口的消息处理程序。简单的说,队列化的消息被发送给消息队列,而非队列化的消息则发送给窗口消息处理程序。在任何情况下,窗口消息处理程序都将获得窗口的所有消息——包括队列化的和非队列化的。窗口消息处理程序是窗口的消息中心。队列化消息基本上是使用者输入的结果,如WM_KEYDOWN、WM_KEYUP、WM_CHAR、WM_MOUSEMOVE、WM_LBUTTONDOWN 、WM_TIMER、WM_PAINT、WM_QUIT。非队列化消息则是其他消息。在许多情况下,非队列化的消息来自呼叫特定的windows函数。 四、SendMessage与PostMessage的区别
SendMessage与PostMessage是在编程过程中使用频率较高的两个函数。 SendMessage是同步的操作,它将消息发送给窗口,除非消息处理完毕,否则该函数不会返回。其返回值表示其他程序处理消息后的返回值。 PostMessage是异步的操作,将一个消息放到与指定窗口创建的线程相关的消息队列中,不等线程处理消息就返回。其返回值表示PostMessage是否执行成功。 五、GetMessage和PeekMessage的区别
区别一: peekmessage不管消息队列里有没有消息都会马上返回,有消息返回消息,没消息返回空值, getmessage等待到有消息的时候才返回, 区别二: peekmessage可以根据参数决定是否将消息保留在队列中, PM_NOREMOVE:该参数指示保留消息 PM_REMOVE:该参数指示移去消息 而getmessage获得消息后回把消息从消息队列中删去。 PeekMessage是一个异步的操作,而GetMessage则是一个同步的操作。 六、TranslateMessage
功能描述:将虚拟键消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessage或PeekMessage时被读出。 返回值: 如果消息被转换(即,字符消息被送到线程的消息队列中),返回非零值。 如果消息是 WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, 或 WM_SYSKEYUP,返回非零值,不考虑转换。 如果消息没有转换(即,字符消息没被送到线程的消息队列中),返回值是零。 备注: TranslateMessage函数不修改由参数lpMsg指向的消息。 TtanslateMessage仅为那些由键盘驱动器映射为ASCII字符的键产生WM_CHAR消息。 如果应用程序为其它用途而处理虚拟键消息,不应调用TranslateMessage函数。例如,如果TranslateAccelerator函数返回一个非零值,则应用程序将不调用TranslateMessage函数。 Windows CE:Windows CE不支持扫描码或扩展键标志,因此,它不支持由TranslateMessage函数产生的WM_CHAR消息中的lKeyData参数(lParam)16-24的取值。 TranslateMessage函数只能用于转换由GetMessage或PeekMessage函数接收到的消息。 |
|