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

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

       在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函数一直出不来。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值