深入浅出MFC笔记(3)

这篇博客详细解析了MFC中消息处理的关键技术,特别是针对WM_COMMAND消息的二万五千里长征。从AfxWndProc开始,通过CWnd::WindowProc、OnCommand、OnCmdMsg等函数在CMyFrameWnd、CMyView、CMyDoc对象间传递,直到找到对应的消息映射处理程序。文章介绍了消息处理的层次结构和流程,帮助理解MFC的消息路由机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >




MFC六大关键技术之六消息的绕行:command routing (消息的二万五千里长征)

LRESULT  AfxWndProc (HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam,CWnd *pWnd) 

{//推动引擎的起始点。在CWinThread:: Run 中被调用

  return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);

}

LRESULT AfxCallWndProc(CWnd* pWnd,,HWND hWnd, UINT nMsg,WPARAM wParam, LPARAM lParam)

{

  LRESULT lResult =  pWnd->WindowProc(nMsg, wParam, lParam);

  return lResult;

} //pWnd-> Window是虚拟函数,调用pWnd指向对象的函数,但子类没有改写其实是CWnd:: WindowProc

LRESULT CWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam){

    AFX_MSGMAP* pMessageMap;

    AFX_MSGMAP_ENTRY* lpEntry;

    if (nMsg == WM_COMMAND) {   // 判断消息是否为WM_COMMAND

          if (OnCommand(wParam, lParam))  return 1L; //①调用 OnCommand是一个CWnd的虚拟函数

          else  return (LRESULT) DefWindowProc (nMsg, wParam, lParam);⑨  

    }//消息往父类别推去

    pMessageMap = GetMessageMap();

    for (; pMessageMap != NULL;pMessageMap = pMessageMap->pBaseMessageMap){

            lpEntry = pMessageMap->lpEntries;

            printlpEntries(lpEntry);

    }

    return 0;  

}

1. 如果①指向CMyFrameWnd  对象,那么调用的是CFrameWnd:: OnCommand

2. 如果①指向CMyView 对象,那么调用的是CView:: OnCommand。而因为CView并没有改写OnCommand,所以调用的其实是CWnd:: OnCommand

BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam){//以第1种情况为例

  return CWnd::OnCommand(wParam, lParam); //

}

BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam){

    return OnCmdMsg(0, 0); //CCmdTarget 的虚拟函数

}//CMyFrameWnd/CMyView/CMyDoc的对象使用CFrameWnd/CView/CDoc::OnCmdMsg

//CMyWinApp对象并没有改写OnCmdMsg ,所以调用的是CCmdTarget::OnCmdMsg

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode){

      CView* pView = GetActiveView();

     if (pView->OnCmdMsg(nID, nCode))  return TRUE;//

     if (CWnd::OnCmdMsg(nID, nCode))   return TRUE;//

       CWinApp* pApp = AfxGetApp();

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

       return FALSE;

}//Frame窗口处理WM_COMMAND 的次序。最先调用的是pView-> OnCmdMsg 

BOOL CView::OnCmdMsg(UINT nID, int nCode){

  if (CWnd::OnCmdMsg(nID, nCode))  return  TRUE;//

  BOOL bHandled = FALSE;

  bHandled = m_pDocument->OnCmdMsg(nID, nCode); //

  return bHandled;

}//View窗口处理WM_COMMAND 的次序。最先调用⑤CWnd::OnCmdMsgCCmdTarget:: OnCmdMsg

BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode){

    AFX_MSGMAP* pMessageMap;

    AFX_MSGMAP_ENTRY* lpEntry;

for (pMessageMap = GetMessageMap() ; pMessageMap != NULL;

pMessageMap = pMessageMap->pBaseMessageMap){

           lpEntry =  pMessageMap->lpEntries;

  printlpEntries(lpEntry);

     }

return FALSE; // not handled

}

如果在映射表中找到了对应的消息,就调用对应的处理例程,然后也就结束了二万五千里长征。如果没找到,长征还没有结束,这时候退守回到CView:: OnCmdMsg ,调用⑥CDocument:: OnCmdMsg

BOOL CDocument::OnCmdMsg(UINT nID, int nCode){

    if (CCmdTarget::OnCmdMsg(nID, nCode)   return TRUE;

    return FALSE;

}

如果在映射表中还是没找到对应消息,这时候退到CFrameWnd::OnCmdMsg,调用⑦CWnd:: OnCmdMsg (也就是CCmdTarge t:: OnCmdMsg

如果在映射表中还是没找到对应消息,再退回到CFrameWnd:: OnCmdMsg,调用⑧CWinApp :: OnCmdMsg(亦即CCmdTarge t:: OnCmdMsg 

还是没找到对应的消息,退回到⑨CWnd::WindowProc,调用 CWnd:: DefWindowProc。你可以想象,在真正的MFC 中这个成员函数必是调用Windows API 函数:: DefWindowProc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值