由于它的易用性,初学者常误认为VC++开发必须使用MFC,这种想法是错误的。作为Application Framework,MFC的使用只能提高某些情况下的开发效率,只起到辅助作用,而不能替代整个Win32 程序设计。
具体内容,请参考http://www.doc88.com/p-107556767008.html 上的资料
若对你有帮助,请采纳。
文件-新建-项目-MFC(在项目类型-visual c++中)-输入名称及存储位置-确定-下一步-选择应用程序类型(单文档/多个文档/基于对话框)-完成。一个简单的应用程序框架就完成了。CChildFrame做为子窗口包含于MDIClient中(可以包含多个),CChildFrame里面则是真实的文档表示窗口CMDITestView了。 我们从这里开始:// CMDITestApp 初始化BOOL CMDITestApp::InitInstance() 做为CWinApp的派生类,通常需要重载InitInstance(), ExitInstance()两个函数,以完成应用的初始化和退出。我们现在关心InitInstance中关于文档模板、窗口处理的部分,而忽略掉一些CommonControl, OLE初始化部分。 整个InitInstance代码如下:BOOL CMDITestApp::InitInstance(){ InitCommonControls()// 这里删减了大量注释和错误处理 CWinApp::InitInstance()AfxOleInit()AfxEnableControlContainer()SetRegistryKey(_T(“应用程序向导生成的本地应用程序“))LoadStdProfileSettings(4)// 加载标准 INI 文件选项(包括 MRU) TRACE(“Before CMultiDocTemplate\n“)// 注册应用程序的文档模板。文档模板 // 将用作文档、框架窗口和视图之间的连接 CMultiDocTemplate* pDocTemplatepDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView))if (!pDocTemplate) return FALSETRACE(“Before AddDocTemplate\n“)AddDocTemplate(pDocTemplate)// 创建主 MDI 框架窗口 TRACE(“Before new CMainFrame\n“)CMainFrame* pMainFrame = new CMainFrameTRACE(“Before pMainFrame->LoadFrame\n“)if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSEm_pMainWnd = pMainFrameTRACE(“Before ParseCommandLine\n“)CCommandLineInfo cmdInfoParseCommandLine(cmdInfo)// 调度在命令行中指定的命令。如果 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 TRACE(“Before ProcessShellCommand\n“)if (!ProcessShellCommand(cmdInfo)) return FALSETRACE(“Before pMainFrame->ShowWindow\n“)// 主窗口已初始化,因此显示它并对其进行更新 pMainFrame->ShowWindow(m_nCmdShow)TRACE(“Before pMainFrame->UpdateWindow\n“)pMainFrame->UpdateWindow()return TRUE} 为了研究整个创建过程,我在其中添加了一些TRACE来跟踪创建顺序。 忽略掉开始的乱七八糟的初始化,从CMultiDocTemplate开始: CMultiDocTemplate* pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE, RUNTIME_CLASS(CMDITestDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CMDITestView))AddDocTemplate(pDocTemplate)(作了一点点简化)这里首先创建了一个CMultiDocTemplate ——文档模板,文档模板包括的三个运行时刻类信息:Document – CMDITestDoc, FrameWnd – CChildFrame, View – CMDITestView。然后通AddDocTemplate函数将新创建的文档模板添加到模板管理器之中(我们以后再研究模板管理器)。 然后创建主框架窗口CMainFrame: CMainFrame* pMainFrame = new CMainFrameif (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE其中,需要研究的是LoadFrame的实现,以及里面都做了些什么。我们稍后研究。 处理命令行,在这里第一个空文档被建立出来: CCommandLineInfo cmdInfoParseCommandLine(cmdInfo)// 调度在命令行中指定的命令。如果用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 if (!ProcessShellCommand(cmdInfo)) // �0�8 这里创建出初始空文档 return FALSE我们一会会重点研究ProcessShellCommand。 最后,显示主窗口: pMainFrame->ShowWindow(m_nCmdShow)pMainFrame->UpdateWindow()至此,WinApp::InitInstance()完成了自己的工作。 上面遗留了三个待研究的分支,让我们现在去研究它们:1、 CDocTemplate2、 CFrameWnd::LoadFrame3、 CWnd::ProcessShellCommand 研究CDocTemplate 我们的例子中是构造了一个CMultiDocTemplate,它是从CDocTemplate派生而来,所以我们主要研究CDocTemplate。CDocTemplate的几个关键属性列表如下: CRuntimeClass* m_pDocClass// class for creating new documents CRuntimeClass* m_pFrameClass// class for creating new frames CRuntimeClass* m_pViewClass// class for creating new views 其中:m_pDocClass表示文档类类型,在此例子中就是CMDITestDocm_pFrameClass表示容纳View窗口的框架窗口类类型,此例中为CChildFramem_pViewClass表示显示文档的View视类类型,此例中为CMDITestView 我们可以这样认为,CDocTemplate用于描述Frame-View-Doc的关系。当然它还有一大堆别的属性,我们暂时先忽略。 一会还会看到CDocTemplate的创建文档、框架、视的过程,OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) // 关键是这里 OnFileNew()if (m_pMainWnd == NULL) bResult = FALSEbreakcase CCommandLineInfo::FileOpen: // 忽略 case CCommandLineInfo::FilePrintTo: // 忽略 case CCommandLineInfo::FilePrint: case CCommandLineInfo::FileDDE: case CCommandLineInfo::AppRegister: case CCommandLineInfo::AppUnregister: } return bResult}进入到ProcessShellCommand,要处理很多种不同命令,我们忽略其它命令,单独看FileNew部分。注意:实际进入到了AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)之中。 AfxGetApp()实际返回了CMDITestApp的唯一实例,它从CWinApp – CWinThread – CCmdTarget – CObject 派生而来。我们没有重载OnCmdMsg,所以进入到CCmdTarget的OnCmdMsg处理中。为了研究,我们删减了一些代码。BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo){ // 这里删减了一些代码 // determine the message number and code (packed into nCode) const AFX_MSGMAP* pMessageMapconst AFX_MSGMAP_ENTRY* lpEntryUINT nMsg = 0// 这里删减了一些代码,处理后 nMsg = WM_COMMAND // 为了简化,删减了一些断言等。以下循环用于查找处理此消息的入口。欢迎分享,转载请注明来源:内存溢出
评论列表(0条)