在这里将讲述SDI程序中application object、the main frame window、the document、the view、the document template object以及the associate string and menu resources之间的关系。
The Windows Application Object
在CWinApp派生类的Implement文件中会有类似CMyApp theApp的语句。theApp是一个全局变量,它就是启动MFC应用程序的机制所在。
以下是MFC应用程序启动的摘要:
1、Windows把应用程序加载到内存;
2、构造全局变量theApp(所有全局变量在程序被载入内存时被构造);
3、Windows调用全局函数WinMain,它是MFC的一部分,等同于无窗口应用程序的main函数---主程序的入口;
4、WinMain寻找到CWinApp派生类的对象theApp;
5、WinMain为theApp调用InitInstance函数,InitInstance函数可以被重载;
6、重载的InitInstance函数启动加载document、显示the main frame and view windows;
7、WinMain为theApp启动Run函数,Run函数负责分派window messages和command messages。
The Document Template Class
在CWinApp派生类的InitInstance中会有如下代码:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CStudentDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CStudentView));
AddDocTemplate(pDocTemplate);
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CStudentDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CStudentView));
AddDocTemplate(pDocTemplate);
这段代码建立了the application class、the document class、the view window class、the main frame window四个类之间的联系。这时,application class的对象已经存在(theApp),但其他四个类的对象还没有构造,MFC的动态创建机制就起到了作用。
一下两个图分别表示了以上四个类之间的关系、四个类的对象之间的关系:
![鍥涗釜绫诲璞$殑鍏崇郴](https://i-blog.csdnimg.cn/blog_migrate/ce7db284be5c6d5d00fb5336ff12155f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/af7d48d044c5346f59d869c2c48d14fb.png)
Creating an Empty Document—The CWinApp::OnFileNew Function
当application class的InitInstance调用完AddDocTemplate以后,它将调用OnFileNew。
OnFileNew做如下事情:
1、构造Document对象,但不从硬盘中读取数据;
2、构造the main frame对象和the main frame window,但不显示它,它包括IDR_MAINFRAME、the toolbar、the status bar;
3、构造view对象和view窗口,但不显示它;
4、建立the document、main frame、view对象之间的关系,这里要借助AddDocTemplate建立的类关系;
5、为document对象调用虚函数CDocument::OnNewDocument,CDocument::OnNewDocument函数将调用虚函数DeleteContent函数;
6、为view对象调用虚函数CView::OnInitialUpdate;
7、为frame对象调用CFrameWnd::ActivateFrame以显示the main frame window(有the menus,view window,control bars)。
The Document Class's OnNewDocument Function
构造函数所完成的工作越少越好,这样构造函数出错的几率就会越来越小。而CDocument::OnNewDocument 和 CView::OnInitialUpdate 是做初始化的好地方。在这里你可以弹出一个MessageBox。如果出错,OnNewDocument还可以返回FALSE。值得注意的是,OnNewDocument可以被调用很多次,所以有些指令需只执行一次的话,就需要做一个“first time” flag成员变量。
Connecting File Open to Your Serialization Code—The OnFileOpen Function
文件打开菜单映射到CWinApp::OnFileOpen函数,它将执行以下几个步骤:
1、提示用户选择一个文件;
2、调用虚函数CDocument::OnOpenDocument,CDocument::OnOpenDocument打开文件,调用CDocument::DeleteContents,并且构造一个CArchive对象。随后调用document的Serialize函数从archive中载入数据;
3、调用view的OnInitialUpdate函数。
Connecting File Save and File Save As to Your Serialization Code
文件保存和另存为菜单映射到CDocument的OnFileSave函数,OnFileSave函数依次调用Serialize函数,它使用一个archive对象进行存储。
The Document's "Dirty" Flag
CDocument有一个protected成员函数m_bModified。可以通过CDocument的函数SetModifiedFlag和IsModified访问m_bModified。当新建一个document或者读取完硬盘上的数据后,m_bModified被Application Framework设为FALSE。当document的内容被改写后要确保把m_bModified设为TRUE。
小结:OnFileNew和OnFileOpen都在Application类中,Application类里面有DocumentTemplate,可以同时调动Document和View(OnInitialUpdate)。
OnFileSave和OnFileSaveAs都在Document类中,它只需做Serialization,不牵扯View的操作,故不需要把它们放在Application类中。