windows 消息队列,消息循环,模态对话框
2013-05-09 20:56
344 查看
Windows的消息队列是基于线程的。
消息队列,消息循环:
线程是程序串行执行的最小单位。
一个典型的Win32项目(不是MFC项目,只有一个窗口的项目),其中的消息循环会使用如下代码实现:
//代码段1
MSG msg
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GetMessage()是取得消息,如果没有消息,线程阻塞在这里,不占用CPU。
DispatchMessage()是将消息分发,分发到所有在这个线程中创建的窗口的窗口处理函数中去。 如果不需要分发消息,就不需要调用DispatchMessage(),例如线程中没有窗口的情况。
线程消息循环:
实际上,任何线程只要调用了上述代码段1中的代码,就已经实现了消息循环的功能。更进一步,其实只要调用GetMessage()函数就可以了。
即:
//代码段2
BOOL bRet; MSG msg;
while( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1 || WM_QUIT == msg.message){
// handle the error and possibly exit
break;
}
}
在工作线程中,只要有代码段2,就可以实现消息循环的功能了。
这是一个很方便的线程间异步通信的机制。给线程发消息用PostThreadMessage()。为什么去掉了DispatchMessage()呢,因为一般情况下,在工作线程中是不需要创建窗口的,不需要分发到窗口中去处理,能从线程的消息队列里取得消息就足够了。
如果设计线程的初衷为:当某条件发生时,让工作线程开始工作,一直将工作完成,之后挂起,等待新条件的发生,等待时不占用CPU资源。 那么代码段2所展示的机制就能很好的完成这样的功能。 而且可以使多个工作线程都用同样的机制实现,彼此间协同工作,加之某种资源共享机制,可以实现一个异步的消息处理链。
模态对话框:
消息循环可以有多个,可以在上一级消息循环的某个消息的处理过程中,局部创建一个消息循环,模态对话框就是采用这种机制创建出来的。
一个线程可以有多个消息循环,并行的消息循环显然没有意义,多个就是在消息循环中嵌套消息循环。
如代码段1中的DispatchMessage函数,将消息派发到窗口的消息处理函数中,WndProc1()。
现在假设在WndProc1()中创建一个消息循环,并且只取得这个窗口本身的消息 GetMessage(&msg, hWnd, 0, 0),不必Dispatch了,因为已经找到了目标窗口,然后用这个窗口真正的消息处理函数去处理。 这样模态对话框存在时,处理了所有的窗口消息,创建模态对话框的窗口就一直得不到处理消息的机会,模块对话框就始终处于最上层,直到其主动退出。
当然,对模态对话框的这种解释是简化了的,实际过程可能复杂的多,取得的窗口消息至少要包含所有的子窗口的消息,也需要Dispatch到相应的子窗口,等等。但是最基本的机制应该就是这样的。
消息队列,消息循环:
线程是程序串行执行的最小单位。
一个典型的Win32项目(不是MFC项目,只有一个窗口的项目),其中的消息循环会使用如下代码实现:
//代码段1
MSG msg
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GetMessage()是取得消息,如果没有消息,线程阻塞在这里,不占用CPU。
DispatchMessage()是将消息分发,分发到所有在这个线程中创建的窗口的窗口处理函数中去。 如果不需要分发消息,就不需要调用DispatchMessage(),例如线程中没有窗口的情况。
线程消息循环:
实际上,任何线程只要调用了上述代码段1中的代码,就已经实现了消息循环的功能。更进一步,其实只要调用GetMessage()函数就可以了。
即:
//代码段2
BOOL bRet; MSG msg;
while( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1 || WM_QUIT == msg.message){
// handle the error and possibly exit
break;
}
}
在工作线程中,只要有代码段2,就可以实现消息循环的功能了。
这是一个很方便的线程间异步通信的机制。给线程发消息用PostThreadMessage()。为什么去掉了DispatchMessage()呢,因为一般情况下,在工作线程中是不需要创建窗口的,不需要分发到窗口中去处理,能从线程的消息队列里取得消息就足够了。
如果设计线程的初衷为:当某条件发生时,让工作线程开始工作,一直将工作完成,之后挂起,等待新条件的发生,等待时不占用CPU资源。 那么代码段2所展示的机制就能很好的完成这样的功能。 而且可以使多个工作线程都用同样的机制实现,彼此间协同工作,加之某种资源共享机制,可以实现一个异步的消息处理链。
模态对话框:
消息循环可以有多个,可以在上一级消息循环的某个消息的处理过程中,局部创建一个消息循环,模态对话框就是采用这种机制创建出来的。
一个线程可以有多个消息循环,并行的消息循环显然没有意义,多个就是在消息循环中嵌套消息循环。
如代码段1中的DispatchMessage函数,将消息派发到窗口的消息处理函数中,WndProc1()。
现在假设在WndProc1()中创建一个消息循环,并且只取得这个窗口本身的消息 GetMessage(&msg, hWnd, 0, 0),不必Dispatch了,因为已经找到了目标窗口,然后用这个窗口真正的消息处理函数去处理。 这样模态对话框存在时,处理了所有的窗口消息,创建模态对话框的窗口就一直得不到处理消息的机会,模块对话框就始终处于最上层,直到其主动退出。
当然,对模态对话框的这种解释是简化了的,实际过程可能复杂的多,取得的窗口消息至少要包含所有的子窗口的消息,也需要Dispatch到相应的子窗口,等等。但是最基本的机制应该就是这样的。
相关文章推荐
- DirectUI中模态对话框和菜单的原理(自己控制整个Windows消息循环。或者,用菜单模拟窗体打开时用SetCapture取得控制权,一旦窗体收到WM_CAPTURECHANGED消息就把窗体退出)
- Windows的消息队列与消息循环
- 事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)
- windows的消息队列与消息循环
- Windows的消息队列与消息循环
- 模态对话框和非模态对话框的消息循环
- 模态对话框和非模态对话框的消息循环
- Windows的消息队列与消息循环
- Windows消息队列,UI线程,窗口以及消息处理方式总结 .
- 弹出菜单中用Domodal显示模态对话框,对话框得不到鼠标消息
- 如何使对话框中接收到WM_CHAR消息(Windows编程)
- windows程序设计 消息循环
- MFC应用程序中处理消息,创建窗口的过程,关闭窗口(非模态窗口),打开模式对话框等的函数调用顺序 .
- windows 消息队列Microsoft Message Queue (MSMQ)实例
- Windows消息队列
- c# .net windows消息队列简单应用示例
- 关于Windows消息队列的几个问题
- 详谈Windows消息循环机制
- 揭开.NET消息循环的神秘面纱(GetMessage()无法取得任何消息,就会进入Idle(空闲)状态,进入睡眠状态(而不是Busy Waiting)。当消息队列不再为空的时候,程序会自动醒过来)
- Qt模态对话框与事件循环