全部博文(263)
分类: WINDOWS
2009-10-27 22:35:37
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo) { BOOL bResult = TRUE; switch (rCmdInfo.m_nShellCommand) { case CCommandLineInfo::FileNew: if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) // 关键是这里 OnFileNew(); if (m_pMainWnd == NULL) bResult = FALSE; break; case CCommandLineInfo::FileOpen: // 忽略 case CCommandLineInfo::FilePrintTo: // 忽略 case CCommandLineInfo::FilePrint: case CCommandLineInfo::FileDDE: case CCommandLineInfo::AppRegister: case CCommandLineInfo::AppUnregister: } return bResult; } |
BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // 这里删减了一些代码 // determine the message number and code (packed into nCode) const AFX_MSGMAP* pMessageMap; const AFX_MSGMAP_ENTRY* lpEntry; UINT nMsg = 0; // 这里删减了一些代码,处理后 nMsg = WM_COMMAND // 为了简化,删减了一些断言等。以下循环用于查找处理此消息的入口。 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; // 未找到则不处理 } |
AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode, AFX_PMSG pfn, void* pExtra, UINT_PTR nSig, AFX_CMDHANDLERINFO* pHandlerInfo) // return TRUE to stop routing { union MessageMapFunctions mmf; mmf.pfn = pfn; BOOL bResult = TRUE; // default is ok if (pHandlerInfo != NULL) { // just fill in the information, don't do it pHandlerInfo->pTarget = pTarget; pHandlerInfo->pmf = mmf.pfn; return TRUE; } switch (nSig) { case AfxSigCmd_v: // normal command or control notification ASSERT(CN_COMMAND == 0); // CN_COMMAND same as BN_CLICKED ASSERT(pExtra == NULL); (pTarget->*mmf.pfnCmd_v_v)(); // ß 实际调用 pTarget 指向的这个成员函数 break; // 下面还有大量的多种 AfxSigCmd_xxx,忽略掉它们。 default: // illegal ASSERT(FALSE); return 0; break; } return bResult; } |
void CWinApp::OnFileNew() { if (m_pDocManager != NULL) m_pDocManager->OnFileNew(); } |
void CDocManager::OnFileNew() { if (m_templateList.IsEmpty()) // 提示没有模板并返回 CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead(); // 第一个 if (m_templateList.GetCount() > 1) // 弹出一个对话框(很难看的)提示用户选择一个文档模板 // 在这个例子里面,pTemplate 就是 CMDITestApp::InitInstance() 里面创建的那个模板 pTemplate->OpenDocumentFile(NULL); } |
> mfc71d.dll!CDocManager::OnFileNew() 行852 C++ mfc71d.dll!CWinApp::OnFileNew() 行25 C++ mfc71d.dll!_AfxDispatchCmdMsg(CCmdTarget * pTarget=0x0042cae8, unsigned int nID=57600, int nCode=0, void (void)* pfn=0x0041153c, void * pExtra=0x00000000, unsigned int nSig=53, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) 行89 C++ mfc71d.dll!CCmdTarget::OnCmdMsg(unsigned int nID=57600, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) 行396 + 0x27 C++ mfc71d.dll!CWinApp::ProcessShellCommand(CCommandLineInfo & rCmdInfo={...}) 行27 + 0x1e C++ MDITest.exe!CMDITestApp::InitInstance() 行101 + 0xc C++ |
CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible) { // 以下代码删减了验证、断言部分 CDocument* pDocument = CreateNewDocument(); // 创建文档对象 CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL); // 创建框架窗口 if (lpszPathName == NULL) { pDocument->OnNewDocument(); // 初始化文档 } else // 打开已有文档 InitialUpdateFrame(pFrame, pDocument, bMakeVisible); return pDocument; } |
CDocument* CDocTemplate::CreateNewDocument() { // default implementation constructs one from CRuntimeClass if (m_pDocClass == NULL) // 错误提示啦 // CRuntimeClass* m_pDocClass -> CreateObject 实例化文档类。 // 在此例子中既是 CMDITestDoc CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject(); AddDocument(pDocument); // 添加到模板里的文档列表,MultiDocTemplate 保存此一文档 return pDocument; } |
class CMDITestDoc : public CDocument { protected: // 仅从序列化创建 CMDITestDoc(); // 被保护的构造函数 DECLARE_DYNCREATE(CMDITestDoc) // 支持从 CRuntimeClass 信息中创建。 |
CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther) { // create a frame wired to the specified document CCreateContext context; // 这个 CreateContext 传递到 LoadFrame 中 context.m_pCurrentFrame = pOther; // 此例中 = NULL context.m_pCurrentDoc = pDoc; // = 刚才创建的文档 context.m_pNewViewClass = m_pViewClass; // 显示此文档的视类的类型 context.m_pNewDocTemplate = this; if (m_pFrameClass == NULL) // 提示错误并返回 // 利用 CRuntimeClass 信息创建框架窗口对象,此例中为 CChildFrame CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject(); // 这里,我们又看到了 LoadFrame , 参考前面的 LoadFrame 吧 // 在这里面,View 窗口也被产生出来。参考 TRACE 输出。 pFrame->LoadFrame(m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame styles NULL, &context); return pFrame; } |
BOOL CMDITestDoc::OnNewDocument() { TRACE("CMDITestDoc::OnNewDocument() entry\n"); if (!CDocument::OnNewDocument()) return FALSE; // TODO: 在此添加重新初始化代码 // (SDI 文档将重用该文档) return TRUE; } |
void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc, BOOL bMakeVisible) { // just delagate to implementation in CFrameWnd pFrame->InitialUpdateFrame(pDoc, bMakeVisible); } |
// 主窗口已初始化,因此显示它并对其进行更新 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); |