收藏 (0) +1 (0) +1 (0) +1
收藏成功查看收藏>>

正在阅读:深入探讨MFC消息循环和消息泵深入探讨MFC消息循环和消息泵

2004-05-31 10:37 出处:CSDN 作者:enoloo 责任编辑:linjixiong


  我做了一个小例子,在对话框类的PreTranslateMessage中,返回FALSE。在主窗口显示这个非模式对话框,在对话框拥有焦点的时候,仍然能够激活主窗口的快捷键。

  总之,整个框架就是让每个消息的目标窗口(包括他的父窗口)都有机会参与消息到来之前的处理。呵呵~

  至此,非对话框的消息循环和消息泵的机制就差不多了。这个机制在一个无限循环中,不断地从消息队列中获取消息,并且保证了程序的线程消息能够得到机会处理,窗口消息在预处理之后被发送到相应的窗口处理过程。那么,还有一点疑问,为什么要一会儿调用::PeekMessage,一会儿调用::GetMessage呢,他们有什么区别?

  NOTE:一般来说,GetMessage被设计用来高效地从消息队列获取消息。如果队列中没有消息,那么函数GetMessage将导致线程休眠(让出CPU时间)。而PeekMessage是判断消息队列中如果没有消息,它马上返回0,不会导致线程处于睡眠状态。

  在上面的phase1第一个内循环中用到了PeekMessage,它的参数PM_NOREMOVE表示并不从消息队列中移走消息,而是一个检测查询,如果消息队列中没有消息他立刻返回0,如果这时线程空闲的话将会引起消息循环调用OnIdle处理过程(上面讲到了这个函数的重要性)。如果将::PeekMessage改成::GetMessage(***),那么如果消息队列中没有消息,线程将休眠,直到线程下一次获得CPU时间并且有消息出现才可能继续执行,这样,消息循环的空闲时间没有得到应用,OnIdle也将得不到执行。这就是为什么既要用::PeekMessage(查询),又要用::GetMessage(做实际的工作)的缘故。

  第二部分: 对话框程序的消息循环机制

  基于对话框的MFC工程和上面的消息循环机制不一样。实际上MFC的对话框工程程序就是模式对话框。他和上面讲到的非对话框程序的不同之处,主要在于应用程序对象的InitInstance()不一样。


//dlg_5Dlg.cpp
BOOL CDlg_5App::InitInstance()
{
 AfxEnableControlContainer();
#ifdef _AFXDLL
 Enable3dControls();   // Call this when using MFC in a shared DLL
#else
 Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

 CDlg_5Dlg dlg; //定义一个对话框对象
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal(); //对话框的消息循环在这里面开始
 if (nResponse == IDOK)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with OK
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with Cancel
 }

 // Since the dialog has been closed, return FALSE so that we exit the
 //  application, rather than start the application's message pump.
 return FALSE;
}

 

  NOTE: InitInstance函数返回FALSE,由最上面程序启动流程可以看出,CWinThread::Run是不会得到执行的。也就是说,上面第一部分说的消息循环在对话框中是不能执行的。实际上,对话框也有消息循环,她的消息循环在CDialog::DoModal()虚函数中的一个RunModalLoop函数中。


察看评论详细内容 我要发表评论
作者笔名 简短内容 发表时间
:

键盘也能翻页,试试“← →”键

相关文章

关注我们

最新资讯离线随时看 聊天吐槽赢奖品
手机访问回到顶部