1. 最简单的框架程序:
使用MFC基础类库,编写一个最简单的框架程序:
#include <afxwin.h>
class CMyApp: public CWinApp
{
public:
BOOL InitInstance();
};
CMyApp MyApp;
BOOL CMyApp::InitInstance()
{
CFrameWnd *pMainWnd = new CFrameWnd;
pMainWnd->Create(NULL, "Basic MFC Application");
pMainWnd->ShowWindow(m_nCmdShow);
pMainWnd->UpdateWindow();
m_pMainWnd = pMainWnd;
return TRUE;
}
注意:工程设置中设置为使用静态MFC库,或动态使用MFC库。
该工程中,除了对CWinApp类进行了继承以外没有任何其的代码,这就如同MFC进化中所讲的原理是相同的。MFC实现了一些基本类,CWinApp,CCmdTarget,CFrameWnd等,只要实现从他们进行继承就可以很简单的代码实现框架程序。
2. 文档视图框架:
MFC将主窗口类分为了三个类,分别负责了不同的工作:文档类(CDocument类)、视图类(CView)、主框架类(CFrameWnd类),分别负责数据的存储管理、数据的显示及接受消息、承担文档类和视图类的容器。
而这三个类又是由文档模板类对象来管理的,它有两个版本,一个是单文档的文档模板类,一个是多文档的文档模板类。在该类的对象初始化的时候动态创建上述的三个对象。
程序员的工作简化成了如下几项:
1. 重写CWinApp派生类的虚函数InitInstance。在这个函数中按照自己的需要创建和显示窗口。
2. 在CDocument的派生类中,声明程序需要的数据和对这些数据进行必要操作的接口函数。
3. 在CView类的派生类中编写处理消息的代码,如果在消息处理中需要文档的数据,调用该类的GetDocument方法获取文档类的对象指针,然后通过文档类的接口函数对该文档的数据进行操作。
4. 在CView类的派生类中的OnDraw函数中编写窗口重绘函数时的代码。
各个部分的关系:
解释:
系统首先在程序启动的时候调用应用程序类的初始化函数,初始化应用程序对象(这个对象在Window 程序中为CWinApp类派生类的对象theApp),应用程序对象初始化完毕后,会创建文档模板类的对象,在这个对象初始化的时候会动态的创建三个类,分别为文档对象,窗口框架对象,视图对象,文档模板类对象负责管理这三个类。其中视图类对象是由窗口框架类的对象创建。
SDI各个对象的联系方法:
解释:
如图所示,调用全局函数AfxGetApp()函数可以获取应用程序对象的指针。调用AfxGetMainWnd()全局函数,可以获得窗口框架类对象的指针,在获得窗口框架类对象之后,通过调用窗口框架类的GetActiveDocument()方法可以获得文档类对象,调用它的GetActiveView()函数可以获得视图类对象。在视图类对象中,调用它的GetDocument()方法可以获得文档类对象的指针。在文档对象类中,调用它的GetFirstViewPostion()、GetNextView()和UpdateAllView()方法可以获得视图类对象。
解释:
如图所示,调用全局函数AfxGetApp()函数可以获取应用程序对象的指针。调用AfxGetMainWnd()全局函数,可以获得窗口框架类对象的指针,在获得窗口框架类对象之后,通过调用窗口框架类的GetActiveFrame()或MDIGetActive()方法可以获得活动的字框架类指针,在子窗口框架类对象中调用GetActiveDocument()方法可以获得文档类对象的指针,调用它的GetActiveView()函数可以获得视图类对象。在视图类对象中,调用它的GetDocument()方法可以获得文档类对象的指针。在文档对象类中,调用它的GetFirstViewPostion()、GetNextView()和UpdateAllView()方法可以获得视图类对象。
文档视图框架消息流动:
解释:
多数的消息首先是由活动视图对象获得的,在该类中找不到相应响应函数,它将该消息传递给文档模板对象,文档模板对象会将该消息传递给文档对象,如果文档对象也没有相应的响应函数,则活动视图对象将该消息传递给其父对象,框架窗口类对象,让其查找响应函数,如果依然没有相应的响应函数,该消息会传递给应用程序类对象,依旧找不到响应函数,最后消息传递给系统的DefWindowProc()方法类做默认处理。
其中,如果消息传递过程中找到了某个响应函数,则该消息不再向下传递。
注: 代码见MFC框架原理。