标签:
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182585
该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COMMAND消息投递流程。基于VS 2005 代码
AfxWndProc最终调用的是OnWndMsg,这个函数负责消息的分发处理。当消息是WM_COMMAND时,将消息投递给OnCommand函数。
- BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- LRESULT lResult = 0;
- union MessageMapFunctions mmf;
- mmf.pfn = 0;
- CInternalGlobalLock winMsgLock;
-
- if (message == WM_COMMAND)
- {
- if (OnCommand(wParam, lParam))
- {
- lResult = 1;
- goto LReturnTrue;
- }
- return FALSE;
- }
-
- }
OnCommand是个虚函数,因为消息是主窗口产生的,所以调用的是CFrameWnd::OnCommand函数该函数先检查该消息是不是在线请求帮助,如果是,则程序给框架窗口发送一个WM_COMMANDHELP消息,否则交由基类CWnd::OnCommand()处理。
- BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
- {
- HWND hWndCtrl = (HWND)lParam;
- UINT nID = LOWORD(wParam);
- CFrameWnd* pFrameWnd = GetTopLevelFrame();
- ENSURE_VALID(pFrameWnd);
- if (pFrameWnd->m_bHelpMode && hWndCtrl == NULL &&
- nID != ID_HELP && nID != ID_DEFAULT_HELP && nID != ID_CONTEXT_HELP)
- {
-
- if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
- SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
- return TRUE;
- }
-
- return CWnd::OnCommand(wParam, lParam);
- }
CWnd::OnCommand首先检查表示控件的LPARAM。如果消息是由控件产生的,LPARAM就会包含控件窗口句柄。如果消息是控件通知,框架就会执行特定的处理过程。如果消息是为某个控件产生的,OnCommand会将消息直接发送给控件,然后OnCommand返回。否则,CWnd::OnCommand()要确保产生命令的界面元素没有被禁用,然后将消息传递给OnCmdMsg函数,调用的是CFrameWnd::OnCmdMsg函数
- BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
- {
- UINT nID = LOWORD(wParam);
- HWND hWndCtrl = (HWND)lParam;
- int nCode = HIWORD(wParam);
-
- if (hWndCtrl == NULL)
- {
-
- if (nID == 0)
- return FALSE;
-
- CTestCmdUI state;
- state.m_nID = nID;
- OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
- if (!state.m_bEnabled)
- {
- TRACE(traceAppMsg, 0, "Warning: not executing disabled command %d/n", nID);
- return TRUE;
- }
-
- nCode = CN_COMMAND;
- }
- else
- {
-
-
- ASSERT(nID == 0 || ::IsWindow(hWndCtrl));
- if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
- return TRUE;
-
- if (ReflectLastMsg(hWndCtrl))
- return TRUE;
-
- if (nID == 0)
- return FALSE;
- }
-
- return OnCmdMsg(nID, nCode, NULL, NULL);
- }
CFrameWnd::OnCmdMsg函数调用时,pExtra和pHandlerInfo是NULL,因为处理命令不需要这一信息。取出的消息按照以下顺序经过应用程序的各个部分:活动视图、活动视图的文档、文档模板、主窗口、应用程序。
- BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
- CPushRoutingFrame push(this);
-
- CView* pView = GetActiveView();
- if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
-
- if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
-
- CWinApp* pApp = AfxGetApp();
- if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
- return FALSE;
- }
- BOOL CView::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
-
- if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
-
- if (m_pDocument != NULL)
- {
-
- CPushRoutingView push(this);
- return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
- }
- return FALSE;
- }
- BOOL CDocument::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
- if (CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
-
- if (m_pDocTemplate != NULL &&
- m_pDocTemplate->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
- return TRUE;
- return FALSE;
- }
- BOOL CDocTemplate::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
- BOOL bReturn;
- CCmdTarget* pFactory = DYNAMIC_DOWNCAST(CCmdTarget, m_pAttachedFactory);
- if (nCode == CN_OLE_UNREGISTER && pFactory != NULL)
- bReturn = pFactory->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
- else
- bReturn = CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
- return bReturn;
- }
上面的一些函数确定了程序执行流程,最终会调用到CCmdTarget::OnCmdMsg,该函数通过查找消息映射表,进而调用到消息处理函数。
- BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
-
-
- const AFX_MSGMAP* pMessageMap;
- const AFX_MSGMAP_ENTRY* lpEntry;
- UINT nMsg = 0;
-
- if (nCode != CN_UPDATE_COMMAND_UI)
- {
- nMsg = HIWORD(nCode);
- nCode = LOWORD(nCode);
- }
-
-
- if (nMsg == 0)
- nMsg = WM_COMMAND;
-
- for (pMessageMap = GetMessageMap(); pMessageMap->pfnGetBaseMap != NULL;
- pMessageMap = (*pMessageMap->pfnGetBaseMap)())
- {
-
- ASSERT(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;
- }
【转】Windows消息投递流程:WM_COMMAND消息流程
标签:
原文地址:http://www.cnblogs.com/wi100sh/p/4210211.html