标签:
一条消息是作为一个结构传递给应用程序的,这个结构中,包含了消息号,消息的类型,字参数和长字参数等信息。结构定义如下:
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
Windows用不同的前缀符号标致不同的消息种类,如BM表示按钮类消息,CB表示组合框消息,DM表示下压式按钮控制消息,EM表示编辑控制消息。
Windows为了给运行程序一个强壮的运行环境,要求每个线程相对独立,系统会为线程分配一些资源,其中比较特殊的是分配一个THREADINFO结构,当线程有了与之相联系的THREADINFO结构时,线程就有了自己的消息队列集合,每个窗口维护自己的消息队列集合,并从中取出消息,再利用窗口函数处理。
BOOL PostMessage(
HWND hWnd, //窗口句柄
UINT Msg, //要发送的消息
WPARAM wParam, //第一个参数
LPARAM lParam //第二个参数
);
当一个线程调用PostMessage函数时,系统首先要知道是哪一个线程建立了用hWnd参数标致的窗口,然后系统分配一块内存,将这个消息参数存储在这块内存中,并将这块内存增加到相应的线程的登记消息队列中。PostMessage函数在登记了消息之后立即返回,因此调用该函数的线程并不知道登记的消息能否被指定的窗口处理。
BOOL PostThreadMessage(
DWORD idThread; //线程标致。
UINT Msg;
WPARAM wParam;
LPARAM lParam
};
要终止消息循环,可以调用PostQuitMessage函数:
void PostQuitMessage(int nExitCode);
该函数实际上不会登记一个消息到任何THREADINFO结构队列中,只是在内部,PostQuitMessage函数设定QS_QUIT唤醒标致,并设置THREADINFO结构的nExitCode成员,因为这些操作永远不会失败,所以PostQuitMessage函数的原型被定义为返回void。
DWORD GetQueueStatus(UINT flags);
参数flags是一个或一组or连接起来的标致,可用来测试特定位。
- QS_ALLEVENTS:输入,WM_TIMER, WM_PAINT,WM_HOTKEY或寄送的消息在队列里。
- QS_ALLINPUT:任何消息在队列里。
QS_ALLPOSTMESSAGE:寄送的消息(而不是其他所列消息)在队列里。
QS_HOTKEY:一条WM_HOTKEY消息在队列里。QS_INPUT:输入消息在队列里。
QS_KEY:一条WM_KEYUP WM_KEYDOWN,WM_SYSKEYUP或WM_SYSKEYDOWN消息在队列里。
QS_MOUSE:WM_MOUSEMOVE消息或鼠标键消息(WM_BUTTONUP WM_RBUTTONDOWN等)在消息队列里。
QS_MOUSEBUTTON:鼠标键消息(WM_LBUTTONUP,WM_RBUTTONDOWN等)在消息队列里。
QS_MOUSEMOVE:WM_MOUSEMOVE消息在消息队列里。
QS_FAINT:WM_PAINT消息在消息队列里。
QS_POSTMESSAGE:寄送的消息(而不是其他所列消息)在队列里。
QS_SENDMESSAGE:由其他线程或应用程序发送的消息在消息队列里。
QS_TIEMR:一条WM_TIEMR消息在消息队列里。
可以通过GetMessage函数从消息队列中提取一个消息。GetMessage函数的原型如下:
GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);
参数说明:
lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消 息,线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin: 要获取消息的最小值,通产设为0。
wMsgFilterMax:要获取消息的最大值,若wMsgFilterMin、wMsgFilterMax均为0,则接受所有消息。
GetMessage 返回 TRUE 的条件是有消息且该消息不为WM_QUIT ;返回 FALSE 的条件是有消息且该消息 为 WM_QUIT 在没有消息的时候等待消息,cpu当然低阻塞。
关于消息的深入分析,可以看这个博客。这个也推荐看看
在提取消息时,系统必须检查队列状态,下图给出消息提取过程线:
(1)如果QS_SENDMESSAGE标志位被设置,系统向相应的窗口过程发送消息。GetMessage函数在窗口过程处理完消息后不返回,要等待其他要处理的消息。
(2)如果消息再消息登记队列中,GetMessage函数填充MSG结构,并返回,这时消息循环通常调用DispatchMessage函数,让窗口过程来处理消息。
(3)如果QS_QIUT标志被设置,GetMessage函数返回一个WM_QIUT消息,并复位QS_QIUT标致。
(4)如果消息再虚拟输入队列,GetMessage函数返回硬件输入消息。
(5)如果QS_TIMER标致被设置,GetMessage函数返回一个WM_TIMER消息。
(6)虽然称为消息队列,但队列中的消息并非总是先进先出。例如只要消息队列中存在WM_QIUT,就会先取出WM_QIUT,导致程序借宿。而只有在没有其它消息时WM_PAINT和WM_TIMER才会被取出。若有多个WM_PAINT或者WM_TIMER,则可能会被合并为一个。
最后用一个简单的图来总结一下流程:
由上图可知,基于消息驱动机制设计Windows应用程序时,程序的基本流程交由Windows去处理。Windows掌握着一定的主动权,全心全意为“接受到的消息找到对应的处理函数”提供服务,而用户只需要集中精力做自己的事情,如编写自己的窗口函数等。
标签:
原文地址:http://blog.csdn.net/q__y__l/article/details/51259911