返回 1
第七章 文档和视图本章导读理解文档类和视图类二者间的关系 。
掌握在视图类中利用 GetDocument函数获得文档类的指针,并借助此指针更新文档类中的数据的方法 。
掌握在文档类 中当文档数 据发生了 改变时利用
UpDateAllViews()通知所有的视图对象的方法,通过调用文档类的 UpDateAllViews()函数去调用每个视图的成员函数 OnUpdate()函数对相应的视图进行数据更新 。
掌握视图类的 OnDraw函数的调用机理 。
了解 SDI文档序列化的工作原理和实现方法 。
返回 2
7.1 文档类和视图类间的关系
视图和用户的文档间是紧密相连的,文档类 用于管理应用程序的数据,包括对数据读取,存储和修改 。 视图类 用于显示文档并管理与用户的交互 。 这种文档和视图的结合,称为,文档 /视图,结构机制 。
定义和操纵数据的代码在文档类中实现;显示数据,
解释用户输入的代码在视图类中实现 。
一个 SDI( 单文档界面 ) 应用程序同一时刻只能打开一个文档 。
在一个 MDI( 多文档界面 ) 应用程序中,可以有几种不同类型的文档,每个文档可以有一个或多个视图 。 同一时刻可以打开几个文档,打开的文档经常使用适合该文档的工具栏和菜单 。
返回 3
7.2 常用的成员函数在 SDI(单文档界面)应用程序中,文档类的基类是
CDocument,它可以有一个或多个视图类,而所有这些视图类的基类都是 CView,任何一个应用程序的文档类和视图类都是由这两个类派生出来的。
7.2.1 CView类的 GetDocument()函数一个视图对象只有一个与之相联系的文档对象,它所包含的 GetDocument()函数可以实现在视图中得到与之相联系的文档 。 CView类及其派生类只需调用 GetDocument()
函数就可以取得 CDocument类的对象指针,从而用此指针来访问文档类中的的所有可见的数据 。
返回 4
GetDocument函数的原型为:
CDocument* CView::GetDocument( ) const;
另外,CDocument类中的 GetNextView()函数可以在文档类中获得视图类的指针
CDocument类先调用 GetFirstViewPosition()函数得到所有有关该文档类对象的第一个视图,再用该函数的返回结果调用 GetNextView()函数,即可得到 CView类的指针,从而借此访问 CView类的数据 。
7.2 常用的成员函数返回 5
这两个函数的原型为:
virtual POSITION CDocument::GetFirstViewPosition( ) const;
virtual CView* CDocument::GetNextView( POSITION& rPosition )
const;
如:
void CMyDoc::OnRepaintAllViews()
{ POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{ CView* pView = GetNextView(pos);
pView->UpdateWindow(); }
}
7.2 常用的成员函数返回 6
7.2.2 CDocument 类的 UpDateAllViews()函数通过文档类的 UpDateAllViews()函数调用每个视图的成员函数 OnUpdate()函数对相应的视图进行数据更新 。
UpDateAllViews()函数的原型为:
void UpDateAllViews(CView*pSender,LPARAM
lHint=0L,CObject*pHint=NULL);
7.2 常用的成员函数返回 7
7.2.3 CView类的 OnUpdate()函数当应用程序调用了 CDocument 类的 UpDateAllViews()函数时,应用程序框架就会相应地调用该函数 。 通常在派生视图类中的 OnUpdate()函数要对文档进行访问,读取文档的数据,然后再对视图的数据成员或控制进行更新 。
OnUpdate()函数原型如下:
virtual void OnUpdate(CView*pSender,LPARAM
lHint,CObject* pHint);
函数中参数的说明同函数 UpdateAllViews()。
利用 OnUpdate()函数,可以使视图的某一部分无效,以便触发视图类的 OnDraw() 函数 。 在默认情况即
lHint=0,pHint=NULL时,函数 OnUpdate()使视图的整个客户区无效;如果想要视图的某一部分无效,则需要定义相关的提示 ( hint) 参数给出准确的无效区域 。
用 OnUpdate()函数来更新视图的滚动范围 。
7.2 常用的成员函数返回 8
7.2.4 Cview 类的 OnlnitialUpdate()函数当应用程序启动或当用户从 【 File】 菜单中选择 【 New】
或 【 Open】 命 令 时,CView 类 中 的 虚 函 数
OnInitialUpdate()都会被自动调用 。 该函数的作用就是调用无提示参数 ( lHint=0,pHint=NULL ) 的
OnUpdate()函数 。
7.2 常用的成员函数返回 9
7.2.5 MFC应用程序中各个类对象间的相互调用关系
(1),在框架窗口类中获得当前的文档类和视图类对象的指针在一个 MDI应用程序中,在框架窗口类 ( 主框架窗口类或子框架窗口类 ) 中,可以利用基类 CFrameWnd 的
GetActiveDocument函数,得到指向当前活动的文档类对象的指针,也可用基类 CFrameWnd的 GetActiveView函数,
得到视图类对象的指针 。 这两个函数的原型如下:
virtual CDocument* GetActiveDocument( );
CView* GetActiveView( ) const;
7.2 常用的成员函数返回 10
(2),获得应用程序类对象的指针在 MFC应用运行过程中,自始至终存在一个应用程序类对象,通过全局的 Windows API函数 AfxGetApp得到应用程序类对象的指针,该函数的原型为:
CWinApp* AfxGetApp( );
(3),从应用程序类对象中获得主框架类对象的指针在 MDI应用程序中,通过 MFC的应用程序类对象,可以获得指向当前系统的主框架窗口类对象的指针,在应用程序类 CWinApp中有一个数据成员 m_pMainWnd,这个数据成员保存了指向应用程序主框架类对象的指针,通过此数据成员可以获得指向主框架类对象的指针 。
7.2 常用的成员函数返回 11
如:
// 获得主框架窗口类对象的指针
CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// 获得当前活动的 MDI子框架窗口的指针
CMDIChildWnd *pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
// 获得当前活动的子框架窗口的活动视图
CMyView *pView = (CMyView *) pChild->GetActiveView();
可以,在程序运行过程中,还可以获得应用程序类对象的指针,从应用程序类对象中也可获得主框架窗口类对象的指针 。
7.2 常用的成员函数返回 12
7.3 在视图类中显示文档类中的数据当用户改变了窗口尺寸,或者窗口恢复了以前被遮盖的部分,或者当应用程序改变了窗口的数据时,窗口都需要重新绘制 。 用户改变窗口的尺寸中,或者窗口恢复以前被遮盖的部分,这两种事件应用程序框架可以自动觉察,并且调用 OnDraw()函数,但如果应用程序的某个函数修改了数据,则必须在程序代码中通过调用视图类所继承的 Invalidate()( 或者 InvalidateRect()) 成员函数来通知 Windows,调用 Invalidate() 函数后会触发对函数
OnDraw()的调用 。
返回 13
7.4 在视图类中响应键盘消息视图是 MFC应用程序中管理视图窗口、处理用户输入以及在视图窗口内或其他设备上显示输入的部分。在上一节中,我们通过视图类实现了把一个简单的消息串显示在视图窗口的中央的功能,在本节中,我们将对上一节的例子进行扩充,实现应用程序响应键盘的输入的功能,即运行该程序时,每从键盘上输入一个字符,便会在视图窗口中显示出所输入的字符。
返回 14
7.5 SDI文档的序列化应用程序中,用户处理的数据往往需要存盘做永久的备份。将文档类中的数据成员变量的值保存在磁盘文件中或将存储的文档文件中的数据读取到相应的成员变量中,这个过程称为序列化( Serialize)。
返回 15
应用程序类的 InitInstance函数在调用了 AddDocTemplate函数之后,
会通过 CWinApp::ProcessShelllCommand间接调用 CWinApp的另一个非常有用的成员函数 OnFleNew,并依次完成下列工作:
1,构造文档对象,但并不从磁盘中读数据;
2,构造主框架类 CMainFrame的对象,并创建该主框架窗口,但不显示;
3,构造视图对象,并创建视图窗口,也不显示;
4,通过内部机制使文档,主框架和视图,对象,之间,真正,建立联系,注意与 AddDocTemplate函数的区别,AddDocTemplate函数建立的是,类,之间的联系;
5.调用文档对象的 CDocument::OnNewDocument虚成员函数,并调用
CDocument::DeleteContents( 消除文档对象的内容 ) 虚函数;
6,调用视图对象的 CView::OnInitialUpdate虚成员函数;
7,调用框架对象的 CFrameWnd::ActiveFrame虚成员函数,以便显示出具有菜单,工具栏,状态栏以及视图窗口的主框架窗口 。
7.5 SDI文档的序列化返回 16
7.5.2 打开文档当 MFC AppWizard创建应用程序时,它会自动将 【 文件
( File) 】 菜单中的 【 打开 ( Open) 】 命令 ( ID号为
ID_FILE_OPEN) 映射到 CWinApp的 OnFileOpen成员函数 。
OnFileOpen函数还会进一步完成下列工作:
1,弹出 【 打开 】 对话框,供用户选择一个文件 。
2,调用文档对象的 CDocument::OnOpenDocument虚成员函数 。 该函数将打开文件,并调用 DeleteContents函数来清除文档对象的内容,然后建立一个 CArchive对象用于数据的读取,接着又自动调用 Serialize函数 。
3,调用视图对象的 CView::OnInitialUpdate虚成员函数 。
7.5 SDI文档的序列化返回 17
7.5.3 保存文档当 MFC AppWizard创建应用程序时,它会自动将 【 文件
( File) 】 菜单中的 【 保存 ( Save) 】 命令与文档类
CDocument 的 OnFileSave 函 数 在 内 部 关 联 起 来 。
OnFileSave函数还会进一步完成下列工作:
1,弹出 【 保存 】 对话框,让用户提供一个文件名 。
2,调用文档对象的 CDocument::OnSaveDocument虚成员函数,接着又自动调用 Serialize函数,并将 CArchive
对象的内容保存在文档中 。
7.5 SDI文档的序列化返回 18
7.5.4 关闭文档当用户试图关闭文档 ( 或退出应用程序 ) 时,应用程序会根据用户对文档的修改与否来进一步完成下列任务:
1,若文档内容已被修改,则弹出一个消息对话框,询问用是户否需要将文档保存 。 如用户选择 【 是 】,则应用程序执行 OnFileSave过程 。
2,调用 CDocument::OnCloseDocument虚成员函数,关闭所有与该文档相关联的文档窗口及相应的视图,调用文档类的 CDocument的 DeleteContents来清除文档数据 。
7.5 SDI文档的序列化返回 19
本章小结
1,文档类和视图类二者间有着密切的关系,在视图类中利用 GetDocument函数可获得文档类的指针,并借助此指针可更新文档类中的数据;在文档类中,当文档数据发生了改变时,可利用 UpDateAllViews()通知所有的视图对象,并可通过调用文档类的 UpDateAllViews()
函数去调用每个视图的成员函数 OnUpdate()函数对相应的视图进行数据更新 。
2,在应用程序中,OnDraw()函数是 CView类中的一个虚成员函数,每次当视图窗口被重新绘制时,应用程序框架都要调用函数 OnDraw()。
3,可以利用文档类中的 Serialize函数来实现文档的序列化,该函数利用 CArchive类对象及插入运算符 ( <<)
和提取运算符 ( >>) 来读写磁盘文件数据 。