消息传递过程--发布日期:2007-9-1


据说是在Run中调用AfxWndProc(侯捷说的我在源码中找了会没找到,也不晓得是哪个间接调用的),在该函数里面接着调用AfxCallWndProc,然后AfxCallWndProc中有这么一段

// special case for WM_INITDIALOG

CRect rectOld;

DWORD dwStyle = 0;

if (nMsg == WM_INITDIALOG)

_AfxPreInitDialog(pWnd, &rectOld, &dwStyle);

// delegate to object's WindowProc

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

// more special case for WM_INITDIALOG

if (nMsg == WM_INITDIALOG)

_AfxPostInitDialog(pWnd, rectOld, dwStyle);

如果不是WM_INITDIALOG消息则调用CWnd的WindowProc,这时就有点迷惑了,应该说CCmdTarget是处理消息的基类其中的OnCmdMsg为什么不先调用呢,其实我也不清楚,查看了源代码后发现在WindowProc中会判断消息的类型里面有这么段:

CWnd::WindowProc

if (message == WM_COMMAND)

{

       if (OnCommand(wParam, lParam))

       {

              lResult = 1;

              goto LReturnTrue;

       }

       return FALSE;

}

       CWnd::OnCommand

如果是命令消息加速键等用户接口对象的WM_COMMAND通知消息(有些控件也会发送此消息比如按钮的单击),则调用OnCommand处理,而在OnCommand中会判断是一般命令消息还是控件消息,其中如果不是控件消息的话会调用OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);看到了吧这里就调用了从CCmdTarget继承来的虚函数(我只找到了CWnd的这个地方调用了改消息)。

接着是控件消息

// special case for notifies

if (message == WM_NOTIFY)

{

       NMHDR* pNMHDR = (NMHDR*)lParam;

       if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))

       goto LReturnTrue;

       return FALSE;

}

关于WM_NOTIFY的一点说明: Win32使用新的WM_NOFITY来处理复杂的通知消息。WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。WM_NOTIFY能传递任意复杂的信息。

因此控件消息也得以处理,WindowProc后面的消息处理可想而知了即其他WM开头的Windows标准消息。

CFrameWnd中改写了OnCmdMsg

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,

       AFX_CMDHANDLERINFO* pHandlerInfo)

{

       CPushRoutingFrame push(this);

       // pump through current view FIRST

       CView* pView = GetActiveView();

       if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))

              return TRUE;

       // then pump through frame

       if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))

              return TRUE;

       // last but not least, pump through app

       CWinApp* pApp = AfxGetApp();

       if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))

              return TRUE;

       return FALSE;

}

由于在CFrameWnd中产生的消息一般都是WM_COMMAND消息,因此当CWnd::WindowProc被调用时会转到OnCommand而CFrameWnd又改写了CWnd的OnCommand那么CFrameWnd的OnCmdMsg是如何被调用的呢,原来在CFrameWnd::OnCommand中调用了CWnd的OnCommand,显然CFrameWnd::OnCmdMsg就被调用了,由上面的CFrameWnd::OnCmdMsg可以清楚的看到CFrameWnd对标准消息传递的过程的改写首先让当前的活动视图处理,通过查看视图的源代码可以发现视图的OnCmdMsg先让CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)处理(最终就是调用CCmdTarget::OnCmdMsg,通过查看源代码可以发现// look through message map to see if it applies to us,其实就是查找此视图及相关基类的消息映射表进行相应的处理),接着是让m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);处理,不用查看文档的代码也可以猜到文档模板的OnCmdMsg会调用,当视图的OnCmdMsg返回后如果没有处理的话又会调用CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)(此时是CFrameWnd处理),最后如果还没有处理的话又给App对象处理,一直到让DefWindowProc处理。

对话框的消息处理与此不同,具体可以根据源代码追踪

呵呵,第一次跟踪查找MFC源代码,不知道以上结论正确与否,不过对我理解消息传递的过程还是有点帮助,写下来以免忘了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值