博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

hardworkor

hardworkor.cublog.cn
mfc文档,视图的创建过程

在网上找了一篇关于mfc文档视图创建过程的文章,和大家一起分享(转载).

很久没有使用MFC了,以至于都忘记MFC框架复杂的窗口、文档、视的创建过程了。

下面我们跟踪一个MFC MDI的应用程序,来温习或学习一下。

 

使用AppWizard创建一个MDI应用程序,我创建的应用程序叫MDITest,这样MFC生成了如下的类:

类名

作用

CMDITestApp

派生于CWinApp的应用程序类。

CMainFrame

派生于CMDIFrameWnd的MDI框架窗口类。

CMDITestDoc

派生于CDocument的文档类。

CChildFrame

派生于CMDIChildWnd的MDI子窗口类。

CMDITestView

派生于CView的文档显示类。

在运行时刻,CMainFrame, CChildFrame, CMDITestView的窗口关系如下面的表格示出:

CMainFrame

Menu, Toolbar

MDIClient

 

CChildFrame

CMDITestView

   pDocument = *CMDITestDoc   (带有文档的指针)

 

 

 

 

 

[StatusBar]

其中,最外层的是顶层窗口CMainFrame,里面包含一个MDIClient窗口。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 ");

     // 注册应用程序的文档模板。文档模板

     // 将用作文档、框架窗口和视图之间的连接

     CMultiDocTemplate* pDocTemplate;

     pDocTemplate = new CMultiDocTemplate(IDR_MDITestTYPE,

         RUNTIME_CLASS(CMDITestDoc),

         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架

         RUNTIME_CLASS(CMDITestView));

     if (!pDocTemplate)

         return FALSE;

     TRACE("Before AddDocTemplate ");

     AddDocTemplate(pDocTemplate);

 

     // 创建主 MDI 框架窗口

     TRACE("Before new CMainFrame ");

     CMainFrame* pMainFrame = new CMainFrame;

     TRACE("Before pMainFrame->LoadFrame ");

     if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

         return FALSE;

     m_pMainWnd = pMainFrame;

 

     TRACE("Before ParseCommandLine ");

     CCommandLineInfo cmdInfo;

     ParseCommandLine(cmdInfo);

 

     // 调度在命令行中指定的命令。如果

     // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。

     TRACE("Before ProcessShellCommand ");

     if (!ProcessShellCommand(cmdInfo))

         return FALSE;

 

     TRACE("Before pMainFrame->ShowWindow ");

     // 主窗口已初始化,因此显示它并对其进行更新

     pMainFrame->ShowWindow(m_nCmdShow);

     TRACE("Before pMainFrame->UpdateWindow ");

     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 CMainFrame;

     if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

         return FALSE;

 

其中,需要研究的是LoadFrame的实现,以及里面都做了些什么。我们稍后研究。

 

处理命令行,在这里第一个空文档被建立出来:

     CCommandLineInfo cmdInfo;

     ParseCommandLine(cmdInfo);

 

     // 调度在命令行中指定的命令。如果用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。

     if (!ProcessShellCommand(cmdInfo))               // ß 这里创建出初始空文档

         return FALSE;

 

我们一会会重点研究ProcessShellCommand

 

最后,显示主窗口:

     pMainFrame->ShowWindow(m_nCmdShow);

     pMainFrame->UpdateWindow();

 

至此,WinApp::InitInstance()完成了自己的工作。

 

上面遗留了三个待研究的分支,让我们现在去研究它们:

1、  CDocTemplate

2、  CFrameWnd::LoadFrame

3、  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

表示文档类类型,在此例子中就是CMDITestDoc

m_pFrameClass

表示容纳View窗口的框架窗口类类型,此例中为CChildFrame

m_pViewClass

表示显示文档的View视类类型,此例中为CMDITestView

 

我们可以这样认为,CDocTemplate用于描述Frame-View-Doc的关系。当然它还有一大堆别的属性,我们暂时先忽略。

 

一会还会看到CDocTemplate的创建文档、框架、视的过程,放在ProcessShellCommand中研究。

 

 

研究LoadFrame

 

让我们继续研究CFrameWnd::LoadFrame是怎么运作的。使用的方法是跟踪进入。。。

BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,

     CWnd* pParentWnd, CCreateContext* pContext)

发表于: 2005-09-29,修改于: 2005-09-29 16:48,已浏览687次,有评论0条 推荐 投诉

给我留言
版权所有 ChinaUnix.net 页面生成时间:0.02818