window程序一个线程中可以有几个消息队列?和几个消息循环
2015-05-04 20:13
627 查看
参看:http://wenku.baidu.com/link?url=Z9UcZPaN0lf9u4MwtkSvt4do3kCPuHISedW3CLyzXsr2uDvhZauc0ziwsYTOK_F2r_ffbnI6myevV7WxaD1WKzD8u1QYTOjh7H86rXdtkQy
在windows中一个线程只有一个消息队列(PostMessage消息队列),非模态对话框的消息在主线程的消息循环中处理,对于模态对话框,其先禁止主窗口,然后自己建立一个消息循环进行消息处理,对话框结束后,停止对话框自己的消息循环,然后enable主窗口。
所以,一个线程中只有一个消息队列(PostMessage消息队列),但是可能存在主线程消息循环外的其他局部消息循环,但是他们不会并行执行。
模态对话框与非模态对话框的内部机制区别:
非模态对话框与APP共用消息循环,不会独占用户 ;模态对话框独占用户输入,其他界面无法响应,有自己的消息循环;
模态对话框的具体实现有以下步骤:
1.让父窗口失效EnableWindow(parentWindow,
FALSE);
2.建立模态对话框自己的消息循环(RunModalLoop);
3.直至接收关闭消息,消息循环终止,并销毁窗口。
具体代码:
模态对话框中的消息循环:
线程主消息循环:
主消息循环与模态对话框中的局部消息循环之间的关系:
![](http://img.blog.csdn.net/20150504202023931?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb3hpYW95dXNoZW5nMjAxMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
当模态对话框显示时,进入模态对话框的消息循环,除非将模态对话框关闭,否则APP的DispatchMessage函数一直出不来。
在windows中一个线程只有一个消息队列(PostMessage消息队列),非模态对话框的消息在主线程的消息循环中处理,对于模态对话框,其先禁止主窗口,然后自己建立一个消息循环进行消息处理,对话框结束后,停止对话框自己的消息循环,然后enable主窗口。
所以,一个线程中只有一个消息队列(PostMessage消息队列),但是可能存在主线程消息循环外的其他局部消息循环,但是他们不会并行执行。
模态对话框与非模态对话框的内部机制区别:
非模态对话框与APP共用消息循环,不会独占用户 ;模态对话框独占用户输入,其他界面无法响应,有自己的消息循环;
模态对话框的具体实现有以下步骤:
1.让父窗口失效EnableWindow(parentWindow,
FALSE);
2.建立模态对话框自己的消息循环(RunModalLoop);
3.直至接收关闭消息,消息循环终止,并销毁窗口。
具体代码:
INT_PTR CDialog::DoModal() { //对话框资源加载 ...... //在创建模态窗口之前先让父窗口失效,不响应键盘、鼠标产生的消息 HWND hWndParent = PreModal(); AfxUnhookWindowCreate(); BOOL bEnableParent = FALSE; if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent)) { ::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; ....... } //创建模态窗口,并进行消息循环,若窗口不关闭,则循环不退出 AfxHookWindowCreate(this); VERIFY(RunModalLoop(dwFlags) == m_nModalResult); //窗口关闭,销毁窗口 DestroyWindow(); PostModal(); //释放资源,并让父窗口有效 pMainWnd->EnableWindow(TRUE); //返回 return m_nModalResult; }
模态对话框中的消息循环:
int CWnd::RunModalLoop(DWORD dwFlags) { //要检查窗口状态是否是模态窗口 //若状态一直为模态,则一直进行消息循环 for (;;) { ASSERT(ContinueModal()); // phase1: check to see if we can do idle work while (bIdle &&!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)) { ASSERT(ContinueModal()); // show the dialog when the message queue goes idle if (bShowIdle) { ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; } // call OnIdle while in bIdle state if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0) { // send WM_ENTERIDLE to the parent ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd); } if ((dwFlags & MLF_NOKICKIDLE) ||!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++)) { // stop idle processing next time bIdle = FALSE; } } //在有消息的情况下取消息处理 do { ASSERT(ContinueModal()); // pump message, but quit on WM_QUIT if (!AfxPumpMessage()) { AfxPostQuitMessage(0); return -1; } // show the window when certain special messages rec'd if (bShowIdle &&(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN)) { ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; } if (!ContinueModal()) goto ExitModal; // reset "no idle" state after pumping "normal" message if (AfxIsIdleMessage(pMsg)) { bIdle = TRUE; lIdleCount = 0; } } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)); } ExitModal: m_nFlags &= ~(WF_MODALLOOP | WF_CONTINUEMODAL); return m_nModalResult; }
线程主消息循环:
//thrdcore.cpp // main running routine until thread exits int CWinThread::Run() { // for tracking the idle time state BOOL bIdle = TRUE; LONG lIdleCount = 0; //消息读取乃至分发 当为WM_QUIT时,退出循环 for (;;) { //检查是否为空闲时刻 while (bIdle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) { // call OnIdle while in bIdle state if (!OnIdle(lIdleCount++)) bIdle = FALSE; // assume "no idle" state } //有消息,读消息并分发 do { // pump message, but quit on WM_QUIT if (!PumpMessage()) return ExitInstance(); // reset "no idle" state after pumping "normal" message if (IsIdleMessage(&m_msgCur)) { bIdle = TRUE; lIdleCount = 0; } } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); } }
主消息循环与模态对话框中的局部消息循环之间的关系:
当模态对话框显示时,进入模态对话框的消息循环,除非将模态对话框关闭,否则APP的DispatchMessage函数一直出不来。
相关文章推荐
- window程序一个线程中可以有几个消息队列?和几个消息循环
- Android异步通信机制简单地理解,Handler是当前线程的消息队列中的一个子队列,而Runable是可以被安排到Handler去运行的接口。 首先在Activity中创建一个继承自Han
- QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)
- 一个可以重用的线程安全生产者消费者队列类
- 这里实现一个基于数组的线程安全的循环队列
- Android 系列 4.11使用活动线程队列和处理程序在线程之间发送消息
- 一个程序是不是可以只有进程没有线程呢?
- 一个简单的Windows程序及消息循环机制
- 主线程中有多个handler的情况,只会共用一个消息队列(看代码)
- 微信小程序统一服务消息下发接口 公众号和小程序消息都可以在一个接口推送了
- 一个线程创建之初是没有消息队列的
- 迅雷笔试题 (JAVA多线程)启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC
- 事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)
- 一个关于消息队列通信的小程序
- 每天一个小程序(8)——顺序循环队列
- 强化一下概念:程序自己不去取消息,消息不会自己跑过来运行(针对线程消息队列里的消息,也是绝大多数消息)
- 让工作线程具有消息队列和消息循环
- FAQ12:每个线程一个消息队列?还是线程中的每个窗口各有一个消息队列?
- Qt 为自己的程序建立一个消息循环
- windows每个线程一个消息队列吗?