MFC下WM_NOTIFY消息处理流程
来源:互联网 发布:网络教育和业余哪个好 编辑:程序博客网 时间:2024/05/29 08:25
参考文章:MFC的消息反射机制
在前一篇文章:MFC消息处理流程概述中描述了MFC消息处理的大体流程。由CWnd::OnWndMsg函数可知,当消息为WM_NOTIFY消息时,调用的是virtual CWnd::OnNotify处理。
if (message == WM_NOTIFY){ NMHDR* pNMHDR = (NMHDR*)lParam; if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))goto LReturnTrue; return FALSE;}
BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult){NMHDR* pNMHDR = (NMHDR*)lParam;HWND hWndCtrl = pNMHDR->hwndFrom;// get the child ID from the window itselfUINT_PTR nID = _AfxGetDlgCtrlID(hWndCtrl);int nCode = pNMHDR->code;// reflect notification to child window controlif (ReflectLastMsg(hWndCtrl, pResult))return TRUE; // eaten by childAFX_NOTIFY notify;notify.pResult = pResult;notify.pNMHDR = pNMHDR;return OnCmdMsg((UINT)nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);}
以上hWndCtrl为子窗口的句柄,通过调用ReflectLastMsg(hWndCtrl, pResult)给子窗口一个自身处理的机会,将消息反射给子窗口处理。ReflectLastMsg返回TRUE,表明子窗口处理了此消息,则OnNotify返回并不交由父窗口处理;反之,表示子窗口未处理此消息,此时,调用OnCmdMsg(...)由父窗口进行处理。 ReflectLastMsg通过层层调用最终会调用CWnd::ReflectChildNotify函数来处理WM_NOTIFY反射消息。
BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult){ CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild); return pWnd->SendChildNotifyLastMsg(pResult);}BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult){ return OnChildNotify(pThreadState->m_lastSentMsg.message, pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);}BOOL CWnd::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult){ return ReflectChildNotify(uMsg, wParam, lParam, pResult);}
CWnd::ReflectChildNotify函数如下:
BOOL CWnd::ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult){// Note: reflected messages are send directly to CWnd::OnWndMsg// and CWnd::OnCmdMsg for speed and because these messages are not// routed by normal OnCmdMsg routing (they are only dispatched)switch (uMsg){ ......case WM_NOTIFY:{// reflect the message through the message map as OCM_NOTIFYNMHDR* pNMHDR = (NMHDR*)lParam;int nCode = pNMHDR->code;AFX_NOTIFY notify;notify.pResult = pResult;notify.pNMHDR = pNMHDR;return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL);} ......}
很显然,调用了virtual CWnd::OnCmdMsg函数来处理,实际上是virtual CCmdTarget::OnCmdMsg函数,CWnd继承自CCmdTarget。
注意:以上return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL)语句,在WM_NOTIFY的基础上+WM_REFLECT_BASE,因为消息流程走到这步,是在子控件窗口的消息映射表中查找反射消息处理函数。
注意区分WM_NOTIFY消息与WM_NOTIFY反射消息,WM_NOTIFY反射消息即消息WM_REFLECT_BASE+WM_NOTIFY,父窗口收到WM_NOTIFY消息而扔给子窗口处理时,为了区分,子窗口处理的消息被译成WM_REFLECT_BASE+WM_NOTIFY消息,否则岂不和子窗口本身的WM_NOTIFY消息混淆了。
BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo){ //从消息映射中查找对应的处理函数 for (pMessageMap = GetMessageMap(); pMessageMap->pfnGetBaseMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)()){lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, nMsg, nCode, nID);if (lpEntry != NULL){// 找到对应的消息处理函数return _AfxDispatchCmdMsg(this, nID, nCode,lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo);}}return FALSE; // not handled 没有对应的消息处理函数则返回FALSE}
在子控件窗口类的消息映射表中没有找到对应的WM_REFLECT_BASE+WM_WM_NOTIFY消息(即对应WM_NOTIFY的反射消息)处理函数返回FALSE,也即以上ReflectLastMsg(hWndCtrl, pResult)返回FALSE,这样父窗口就会处理。 否则,在_AfxDispatchCmdMsg函数中会调用对应的反射消息处理函数处理,ReflectLastMsg(hWndCtrl, pResult)返回TRUE,这样父窗口就不会处理了。
- MFC下WM_NOTIFY消息处理流程
- MFC消息处理流程
- WM_NOTIFY消息流程实例分析
- MFC消息处理流程概述
- MFC消息处理流程概述
- MFC消息处理流程概述
- MFC中的消息处理流程
- MFC消息处理流程概述
- 【MFC消息】 全面解读WM_NOTIFY NMHDR结构
- MFC中的WM_NOTIFY消息的反射
- MFC下的消息处理
- WM_NOTIFY消息
- WM_NOTIFY消息
- WM_NOTIFY消息
- WM_NOTIFY消息
- WM_NOTIFY消息
- WM_NOTIFY消息
- WM_NOTIFY消息
- Android基础类之BaseAdapter
- 2011-2012 年终总结
- shopex本地安装环境-phpnow环境配置 超级简单!
- 系统框图
- WPF学习一:命令
- MFC下WM_NOTIFY消息处理流程
- 杂记
- 完成端口例程
- Using Renewable Energy in the Data Center
- JBPM4.4安装(Tomcat-MySQL)
- 更新ListView某一行
- 2012.10.07 安卓游戏开发笔记(十二)_SurfaceView视图
- Android SurfaceView 的基本应用
- LeetCode: Jump Game II