CSDN博客

img ToCpp

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

发表于2008/10/2 18:36:00  497人阅读


据说是在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消息则调用CWndWindowProc,这时就有点迷惑了,应该说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被调用时会转到OnCommandCFrameWnd又改写了CWndOnCommand那么CFrameWndOnCmdMsg是如何被调用的呢,原来在CFrameWnd::OnCommand中调用了CWndOnCommand,显然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

相关博文

我的热门文章

img
取 消
img