window程序一个线程中可以有几个消息队列?和几个消息循环

来源:互联网 发布:java 视频播放控件 编辑:程序博客网 时间:2024/05/16 08:54

     参看:http://wenku.baidu.com/link?url=Z9UcZPaN0lf9u4MwtkSvt4do3kCPuHISedW3CLyzXsr2uDvhZauc0ziwsYTOK_F2r_ffbnI6myevV7WxaD1WKzD8u1QYTOjh7H86rXdtkQy

       在windows中一个线程只有一个消息队列(PostMessage消息队列),非模态对话框的消息在主线程的消息循环中处理,对于模态对话框,其先禁止主窗口,然后自己建立一个消息循环进行消息处理,对话框结束后,停止对话框自己的消息循环,然后enable主窗口。

        所以,一个线程中只有一个消息队列(PostMessage消息队列),但是可能存在主线程消息循环外的其他局部消息循环,但是他们不会并行执行。


       模态对话框与非模态对话框的内部机制区别:

       非模态对话框与APP共用消息循环,不会独占用户 ;模态对话框独占用户输入,其他界面无法响应,有自己的消息循环;

     模态对话框的具体实现有以下步骤:

     1.让父窗口失效EnableWindow(parentWindow, FALSE);

     2.建立模态对话框自己的消息循环(RunModalLoop);

      3.直至接收关闭消息,消息循环终止,并销毁窗口。

具体代码:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. INT_PTR CDialog::DoModal()  
  2. {  
  3.     //对话框资源加载  
  4.             ......  
  5.           
  6.     //在创建模态窗口之前先让父窗口失效,不响应键盘、鼠标产生的消息  
  7.     HWND hWndParent = PreModal();  
  8.     AfxUnhookWindowCreate();  
  9.     BOOL bEnableParent = FALSE;  
  10.   
  11.     if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent))  
  12.     {  
  13.         ::EnableWindow(hWndParent, FALSE);  
  14.         bEnableParent = TRUE;  
  15.         .......  
  16.     }  
  17.       
  18.     //创建模态窗口,并进行消息循环,若窗口不关闭,则循环不退出  
  19.     AfxHookWindowCreate(this);  
  20.     VERIFY(RunModalLoop(dwFlags) == m_nModalResult);  
  21.   
  22.     //窗口关闭,销毁窗口  
  23.     DestroyWindow();  
  24.     PostModal();  
  25.   
  26.     //释放资源,并让父窗口有效  
  27.     pMainWnd->EnableWindow(TRUE);  
  28.   
  29.     //返回  
  30.     return m_nModalResult;  
  31. }  

模态对话框中的消息循环:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int CWnd::RunModalLoop(DWORD dwFlags)  
  2. {  
  3.    //要检查窗口状态是否是模态窗口  
  4.    //若状态一直为模态,则一直进行消息循环  
  5.    for (;;)  
  6.    {  
  7.        ASSERT(ContinueModal());  
  8.   
  9.        // phase1: check to see if we can do idle work  
  10.        while (bIdle &&!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))  
  11.        {  
  12.           ASSERT(ContinueModal());  
  13.           // show the dialog when the message queue goes idle  
  14.           if (bShowIdle)  
  15.           {  
  16.               ShowWindow(SW_SHOWNORMAL);  
  17.               UpdateWindow();  
  18.               bShowIdle = FALSE;  
  19.           }  
  20.           // call OnIdle while in bIdle state  
  21.           if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)  
  22.           {  
  23.               // send WM_ENTERIDLE to the parent  
  24.                 ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);  
  25.           }  
  26.           if ((dwFlags & MLF_NOKICKIDLE) ||!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))  
  27.           {  
  28.              // stop idle processing next time  
  29.              bIdle = FALSE;  
  30.           }  
  31.        }  
  32.   
  33.     //在有消息的情况下取消息处理  
  34.       do  
  35.       {  
  36.           ASSERT(ContinueModal());  
  37.           // pump message, but quit on WM_QUIT  
  38.           if (!AfxPumpMessage())  
  39.           {  
  40.               AfxPostQuitMessage(0);  
  41.               return -1;  
  42.           }  
  43.           // show the window when certain special messages rec'd  
  44.           if (bShowIdle &&(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))  
  45.           {  
  46.               ShowWindow(SW_SHOWNORMAL);  
  47.               UpdateWindow();  
  48.               bShowIdle = FALSE;  
  49.           }  
  50.       
  51.           if (!ContinueModal())  
  52.               goto ExitModal;  
  53.           // reset "no idle" state after pumping "normal" message  
  54.           if (AfxIsIdleMessage(pMsg))  
  55.           {  
  56.               bIdle = TRUE;  
  57.               lIdleCount = 0;  
  58.           }  
  59.       }   
  60.       while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));  
  61.    }  
  62.   
  63.    ExitModal:  
  64.        m_nFlags &= ~(WF_MODALLOOP | WF_CONTINUEMODAL);  
  65.        return m_nModalResult;  
  66. }  

线程主消息循环:
[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. //thrdcore.cpp    
  2. // main running routine until thread exits    
  3. int  CWinThread::Run()  
  4. {  
  5.     // for tracking the idle time state    
  6.     BOOL bIdle = TRUE;  
  7.     LONG lIdleCount = 0;  
  8.   
  9.     //消息读取乃至分发 当为WM_QUIT时,退出循环  
  10.     for (;;)  
  11.     {  
  12.         //检查是否为空闲时刻  
  13.         while (bIdle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))  
  14.         {  
  15.             // call OnIdle while in bIdle state    
  16.             if (!OnIdle(lIdleCount++))  
  17.                 bIdle = FALSE; // assume "no idle" state    
  18.         }  
  19.       
  20.         //有消息,读消息并分发  
  21.         do  
  22.         {  
  23.             // pump message, but quit on WM_QUIT    
  24.             if (!PumpMessage())  
  25.                 return ExitInstance();  
  26.   
  27.             // reset "no idle" state after pumping "normal" message    
  28.             if (IsIdleMessage(&m_msgCur))  
  29.             {  
  30.                 bIdle = TRUE;  
  31.                 lIdleCount = 0;  
  32.             }  
  33.               
  34.         }  
  35.         while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));  
  36.      }  
  37. }  


主消息循环与模态对话框中的局部消息循环之间的关系:



当模态对话框显示时,进入模态对话框的消息循环,除非将模态对话框关闭,否则APPDispatchMessage函数一直出不来。


http://blog.csdn.net/xiaoxiaoyusheng2012/article/details/45484669


0 0