090923(星期三):MFC消息路由8, Frame8代码分析,ONCOMMAND消息的多线索流动

Wednesday, September 23, 2009

 

一、Frame8Command消息的分发

       cout << endl << "pMyView received a WM_COMMAND, routing path :" << endl;

       AfxWndProc(0, WM_COMMAND, 0, 0, pMyView);

1,函数调用栈:

AfxCallWndProc(pMyView, 0, WM_COMMAND, 0, 0);

pMyView ->WindowProc(WM_COMMAND, 0, 0);

 

2,代码进入:

注意this指针指向CMyView

LRESULT CWnd::WindowProc(WM_COMMAND, 0, 0)

{

       AFX_MSGMAP* pMessageMap;

       AFX_MSGMAP_ENTRY* lpEntry;

 

       if (nMsg == WM_COMMAND) // special case for commands

       {

L5:          if (OnCommand(wParam, lParam))

                     return 1L; // command handled

              else

L8:                 return (LRESULT)DefWindowProc(nMsg, wParam, lParam);

       }

 

       pMessageMap = GetMessageMap();

 

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

       {

              lpEntry = pMessageMap->lpEntries;

              printlpEntries(lpEntry);

       }

       return 0; // add by JJHou. if find, should call lpEntry->pfn,

       // otherwise should call DefWindowProc.

}

 

3Line5OnCommand的执行

              if (OnCommand(wParam, lParam))详细看看这个句子:

pMyView-> OnCommand

CMyViewCView类都没有重写OnCommand

再基类CWndOnCommand函数的定义,this指针还是指向CMyView

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

{

       // ...

       return OnCmdMsg(0, 0);

}

 

4OnCommand的执行

于是上面的一句OnCommand00);

实际上是调用CMyView:OnCommand;

但是CMyView没有重写这个重写这个虚函数,CView重写了,继续调用:

BOOL CView::OnCmdMsg(UINT nID, int nCode) // this指针还是CMyView

{

L1:   if (CWnd::OnCmdMsg(nID, nCode))

              return TRUE;

 

       BOOL bHandled = FALSE;

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

       return bHandled;

}

 

 

5,看看上面CWnd::OnCmdMsg(0, 0)的执行过程

CWnd并没有复习OnCmdMsg函数,

执行的代码是:this指针仍然是指向pMyView的,这决定了GetMessageMap返回的内容。

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

{

       // Now look through message map to see if it applies to us

       AFX_MSGMAP* pMessageMap;

       AFX_MSGMAP_ENTRY* lpEntry;

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

       {

              lpEntry = pMessageMap->lpEntries;

              printlpEntries(lpEntry);  // 继续那个只能打印第一条的打印函

       }

 

       return FALSE; // not handled

}

于是第4项目,L1的输出是:

1221 CMyView

122 CView

12 CWnd

1 CCmdTarget

 

6,第4项目L4的执行

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

CMyDocument是被CMyView聚合的,自然可以能用上面的方式增强功能。

CMyDocument没有重写OnCmdMsg,其基类进行了重写

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

{

       if (CCmdTarget::OnCmdMsg(nID, nCode))  // 按照代码看,加入了返回值的判断。

              return TRUE;

 

       return FALSE;

}

由于这些函数在执行时this指针一直是指向CMyDoc的,所以

打印结果:

131 CMyDoc

13 CDocument

1 CCmdTarget

 

7,由于OnCmdMsg的代码都是调用CCmdTarget::OnCmdMsg实现的,这个函数默认返回FALSE,调用者保持返回值不变,一路返回FALSEWindowProc进入L8分支:

LRESULT CWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

       return TRUE;

}

 

CWnd::WindowProc返回了。

 

 

8,总结

消息分开在两个线索中处理是写在

CView::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;

}

意思是如果CView系的类没有出来Cmd消息,返回先不返回,再给下面被聚合的CMyDocument看看是不是需要处理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值