windows消息的循环机制
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
windows消息的循环机制
⾸先来了解⼏个基本概念:
消息:在了解什么是消息先来了解什么是事件。
事件可分为⼏种,由输⼊设备触发的,⽐如⿏标键盘等等。
由窗体控件触发的,⽐如button控件,file菜单等。
还有就是来⾃
Windows内部的事件。
这三种称为事件。
⽽消息,是由事件翻译⽽来的。
事件产⽣消息。
从数据结构⾓度来讲,消息是⼀种结构体。
结构如下:
typedef struct tagMSG
{
HWND hwnd; //窗⼝句柄。
UINT message;//消息类型。
WPARAM wParam;//32位附加信息。
LPARAM lParam;//32位附加信息。
DWORD time;//消息发送时间。
POINT pt;//消息发送时,⿏标所在位置。
}MSG;
消息队列:消息队列有两种,分为系统消息队列和应⽤程序消息队列。
产⽣的消息⾸先由Windows系统捕获,放在系统消息队列,再拷贝到对应的应⽤程序消息队列。
32/64位
系统为每⼀个应⽤程序维护⼀个消息队列。
消息循环:系统为每个应⽤程序维护⼀个消息循环,消息循环会不断检索⾃⾝的消息队列。
每有⼀个消息,就⽤GetMessage()取出消息。
while(GetMessage (&msg, NULL, 0, 0))//Windows消息循环。
{
TranslateMessage (&msg) ;//翻译消息,如按键消息,翻译为WM_CHAR
DispatchMessage (&msg) ;//分发消息到对应窗⼝
}
GetMessage具有阻塞机制。
当消息队列中没有消息时,程序⾮忙等,⽽是让权等待。
当收到WM_QUIT时,GetMessage返回false,循环停⽌,同时应⽤程序终⽌。
消息处理:DispatchMessage()把取出来的消息分配给相应的窗⼝或线程,由窗⼝过程处理函数DefWindowProc()处理。
==============================================================================================================================================================割割割割割
以上简要地介绍了消息队列,消息循环与消息处理的概念。
Windows的应⽤程序靠消息驱动来实现功能。
⽽消息驱动靠消息机制来处理。
消息机制就是由消息队列,消息循环,消息处理构成的。
那么,消息机制是如何运作的呢?
当⽤户运⾏⼀个应⽤程序,通过对⿏标的点击或键盘按键,产⽣⼀些特定事件。
由于Windows⼀直监控着I/O设备,该事件⾸先会被翻译成消息,由系统捕获,存放于系统消息队
列。
经分析,Windows知道该消息应由那个应⽤程序处理,则拷贝到相应的应⽤程序消息队列。
由于消息循环不断检索⾃⾝的消息队列,当发现应⽤程序消息队列⾥有消息,就
⽤GetMessage()取出消息,封装成Msg()结构。
如果该消息是由键盘按键产⽣的,⽤TranslateMessage()翻译为WM_CHAR消息,否则,⽤DisPatchMessage()将取出的消息分
发到相应的应⽤程序窗⼝,交由窗⼝处理程序处理。
Windows为每个窗体预留了过程窗⼝函数,该函数是⼀个回掉函数,由系统调⽤,应⽤程序不能调⽤。
程序员可以通过重载
该函数处理我们”感兴趣”的消息。
对于不感兴趣的消息,则由系统默认的窗⼝过程处理程序做出处理。
下⾯看这么⼀张图:
这张图很好地解释了消息机制的运⾏原理。
当运⾏程序->事件操作引发消息->消息先存在系统消息队列->再存⼊到应⽤程序消息队列->⽤消息循环提取消息->处理消息->再返回消息队列....
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
上⾯代码的执⾏过程为:
1. 消息循环调⽤GetMessage()从消息队列中查找消息进⾏处理,如果消息队列为空,程序将停⽌执⾏并等待(程序阻塞)。
2. 事件发⽣时导致⼀个消息加⼊到消息队列(例如系统注册了⼀个⿏标点击事件),GetMessage()将返回⼀个正值,这表明有消息需要被处理,并且消息已经填充到传⼊的MSG参数中;当传⼊WM_QUIT消息时返回0;
如果返回值为负表明发⽣了错误。
3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做⼀些额外的处理:将虚拟键值信息转换为字符信息。
这⼀步实际上是可选的,但有些地⽅需要⽤到这⼀步。
4. 上⾯的步骤执⾏完后,将消息传递给DispatchMessage()函数。
DispatchMessage()函数将消息分发到消息的⽬标窗⼝,并且查找⽬标窗⼝过程函数,给窗⼝过程函数传递窗⼝句柄、消息、wParam、lParam等参数然
后调⽤该函数。
5. 在窗⼝过程函数中,检查消息和其他参数,你可以⽤它来实现你想要的操作。
如果不想处理某些特殊的消息,你应该总是调⽤DefWindowProc()函数,系统将按按默认的⽅式处理这些消息(通常认为是不做任何操
作)。
6. ⼀旦⼀个消息处理完成,窗⼝过程函数返回,DispatchMessage()函数返回,继续循环处理下⼀个消息。