MFC消息的路由(转载)

MFC消息的路由...

  (2010-12-18 20:31:38)
首先消息分三类,分别是窗口消息,命令消息,通告消息。其中窗口消息的“流动”是很规则的,只是纵向流动,只能从派生类流到基类,最终“流到”基类 CCmdTarget... 绝无“旁逸斜出”的可能。命令消息和通告消息则不同。下面以命令消息来讲述命令消息的“路由”。

 MFC消息的路由...

 

dispatch一个消息时,消息首先由AfxWndProc分发,在经由AfxCallWndProc保存消息,最终调用对应的WindowProc.WindowProc中判断是否是命令消息或者通告消息,是的话,分别交由OnCommandOnNotify处理。不是的话最后交给窗口过程处理。下面讨论命令消息的路由。

   不妨假设调用了CFrameWnd::OnCmdMsg,

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode)
{
   ... ...
    CView* pView = GetActiveView();
  if (pView->OnCmdMsg(nID, nCode))  //(1)
            return TRUE;
      ... ...
  if (CWnd::OnCmdMsg(nID, nCode))  //(4)
            return TRUE;
     ... ...
    CWinApp* pApp = AfxGetApp();

    if (pApp->OnCmdMsg(nID, nCode))  //(5)
            return TRUE;
    return FALSE;
}

 

由于在CFrameWnd中有CView* m_pViewActive; GetActiveView函数返回的就是与这个框架窗口关联的视类对象。流程转到(1),

(1):pView->OnCmdMsg,于是
BOOL CView::OnCmdMsg(UINT nID, int nCode)
{
    ... ...
  if (CWnd::OnCmdMsg(nID, nCode))   //(2)
        return TRUE;
    BOOL bHandled = FALSE;
  bHandled = m_pDocument->OnCmdMsg(nID, nCode);  //(3)

    return bHandled;
}

消息最终由视类中的OnCmdMsg处理,而视类的OnCmdMsg并没有改写,所以最终调用CCmdTarge::OnCmdMsg(),这个函数最终会调用_AfxDispatchCmdMsg[文章的最好附注该函数的定义]对命令消息进行分发处理[其他的分析和这个类似。],如果没处理,再交由(3),由与这个视类关联的文档类处理。其中CDocument* m_pDocument;CView的成员变量。如果(2),(3)都没处理,则流程返回(4),由框架类处理,如果框架类也没处理,则转到(5),由应用程序类处理。这就是命令消息的处理流程。

 

MFC消息的路由...

 

AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,
 AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo)
  // return TRUE to stop routing
{
 ASSERT_VALID(pTarget);
 UNUSED(nCode);   // unused in release builds

 union MessageMapFunctions mmf;
 mmf.pfn = pfn;
 BOOL bResult = TRUE; // default is ok

 if (pHandlerInfo != NULL)
 {
  // just fill in the information, don't do it
  pHandlerInfo->pTarget = pTarget;
  pHandlerInfo->pmf = mmf.pfn;
  return TRUE;
 }

 switch (nSig)
 {
 case AfxSig_vv:
  // normal command or control notification
  ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  ASSERT(pExtra == NULL);
  (pTarget->*mmf.pfn_COMMAND)();
  break;

 case AfxSig_bv:
  // normal command or control notification
  ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  ASSERT(pExtra == NULL);
  bResult = (pTarget->*mmf.pfn_bCOMMAND)();
  break;

 case AfxSig_vw:
  // normal command or control notification in a range
  ASSERT(CN_COMMAND == 0);        // CN_COMMAND same as BN_CLICKED
  ASSERT(pExtra == NULL);
  (pTarget->*mmf.pfn_COMMAND_RANGE)(nID);
  break;

 case AfxSig_bw:
  // extended command (passed ID, returns bContinue)
  ASSERT(pExtra == NULL);
  bResult = (pTarget->*mmf.pfn_COMMAND_EX)(nID);
  break;

 case AfxSig_vNMHDRpl:
  {
   AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
   ASSERT(pNotify != NULL);
   ASSERT(pNotify->pResult != NULL);
   ASSERT(pNotify->pNMHDR != NULL);
   (pTarget->*mmf.pfn_NOTIFY)(pNotify->pNMHDR, pNotify->pResult);
  }
  break;
 case AfxSig_bNMHDRpl:
  {
   AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
   ASSERT(pNotify != NULL);
   ASSERT(pNotify->pResult != NULL);
   ASSERT(pNotify->pNMHDR != NULL);
   bResult = (pTarget->*mmf.pfn_bNOTIFY)(pNotify->pNMHDR, pNotify->pResult);
  }
  break;
 case AfxSig_vwNMHDRpl:
  {
   AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
   ASSERT(pNotify != NULL);
   ASSERT(pNotify->pResult != NULL);
   ASSERT(pNotify->pNMHDR != NULL);
   (pTarget->*mmf.pfn_NOTIFY_RANGE)(nID, pNotify->pNMHDR,
    pNotify->pResult);
  }
  break;
 case AfxSig_bwNMHDRpl:
  {
   AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;
   ASSERT(pNotify != NULL);
   ASSERT(pNotify->pResult != NULL);
   ASSERT(pNotify->pNMHDR != NULL);
   bResult = (pTarget->*mmf.pfn_NOTIFY_EX)(nID, pNotify->pNMHDR,
    pNotify->pResult);
  }
  break;
 case AfxSig_cmdui:
  {
   // ON_UPDATE_COMMAND_UI or ON_UPDATE_COMMAND_UI_REFLECT case
   ASSERT(CN_UPDATE_COMMAND_UI == (UINT)-1);
   ASSERT(nCode == CN_UPDATE_COMMAND_UI || nCode == 0xFFFF);
   ASSERT(pExtra != NULL);
   CCmdUI* pCmdUI = (CCmdUI*)pExtra;
   ASSERT(!pCmdUI->m_bContinueRouting);    // idle - not set
   (pTarget->*mmf.pfn_UPDATE_COMMAND_UI)(pCmdUI);
   bResult = !pCmdUI->m_bContinueRouting;
   pCmdUI->m_bContinueRouting = FALSE;     // go back to idle
  }
  break;

 case AfxSig_cmduiw:
  {
   // ON_UPDATE_COMMAND_UI case
   ASSERT(nCode == CN_UPDATE_COMMAND_UI);
   ASSERT(pExtra != NULL);
   CCmdUI* pCmdUI = (CCmdUI*)pExtra;
   ASSERT(pCmdUI->m_nID == nID);           // sanity assert
   ASSERT(!pCmdUI->m_bContinueRouting);    // idle - not set
   (pTarget->*mmf.pfn_UPDATE_COMMAND_UI_RANGE)(pCmdUI, nID);
   bResult = !pCmdUI->m_bContinueRouting;
   pCmdUI->m_bContinueRouting = FALSE;     // go back to idle
  }
  break;

 // general extensibility hooks
 case AfxSig_vpv:
  (pTarget->*mmf.pfn_OTHER)(pExtra);
  break;
 case AfxSig_bpv:
  bResult = (pTarget->*mmf.pfn_OTHER_EX)(pExtra);
  break;

 default:    // illegal
  ASSERT(FALSE);
  return 0;
 }
 return bResult;

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值