windows 消息处理机制是这样的 :
首先 Windows OS 把来自硬件 ( 鼠标 , 键盘等消息 ) 和来自应用程序的消息放到一个 OS 系统消息队列中去 , 而应用程序需要有自己的消息队列 , 也就是线程消息队列,每一个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列 . windows 消息队列把得到的消息发送到线程消息队列 , 线程消息队列每次取出一条消息发送到指定窗口 , 不断循环直到程序退出 . 这个循环就是靠消息环
while(GetMessage() )
{ TranslateMessage();
DispatchMessage(); }
实现的 .GetMessage() 只是从线程消息中取出一条消息 , 而 DispatchMessage
则把取出的消息发送到目的窗口 . 如果收到 WM_CLOSE 消息则结束循环 , 发送 postqiutmessage(0), 处理 WM_DESTROY 销毁窗口
Windows 消息队列 UI 线程,窗口以及消息处理方式总结
1 Windows UI thread:
2 每个窗体是一个 UI thread ,还是只有一个 UI thread , 所有的窗体都用这一个 UI thread
3 Message queue: 每个窗体都有一个 message queue ,还是共用一个 message queue
4 message 处理:是同步还是异步。是每次处理一个消息等这个消息处理完后再处理另一个消息还是每次取一个不等这个消息处理完就处理下一个,也就是 dispatchmessage 什么时候返回?
答案是要等这个消息处理函数处理完以后才返回,否则会造成消息处理的混乱
5 message 的结构是什么:包含了窗体的 handle ,消息的类型等
在 Winuser.h 中有定义如下:
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
其中的成员变量 message 是 WM_SIZE 、 WM_COMMAND 、 WM_QUIT 等等消息标识。
hwnd 中是这个消息所在的窗口句柄。
6 Windows 如何知道消息应该送到哪一个线程,
这里我们要分为两种情况 , 消息是不是队列消息 , 比如在一个窗体空白处点击左键 , 首先 OS 会根据当前的 context 来生成 MSG , MSG 中会包括要发送到的窗口的 Handle, 这就是一个队列消息 , 首先 OS 会将这个消息放到 OS 的系统消息队列中 , 而后 OS 会有专门的进程根据 MSG 中的窗口的 Handle 找到创建该窗口的线程,而后将该 MSG 送到该线程的消息队列,而后由该消息循环来处理这个消息, 最终由Dispatchmessage 函数来将这个消息送到相应的窗口处理函数。
如果你在一个窗体上点击了一个 button 呢,消息的路径是怎样的呢?当你点击了一个 button 后, OS 产生三个MSG。 WM_LBUTTONDOWN和WM_LBUTTONUP,这两个消息的窗口Handle为button的handle。一个 WM_command 或者 wm_notify 消息, OS 会将这个消息直接送给包含 button 的 window processdure 来处理,而不会将这个送到消息队列。