Visual C++第06章 框架窗口、文档和视图.doc_第1页
Visual C++第06章 框架窗口、文档和视图.doc_第2页
Visual C++第06章 框架窗口、文档和视图.doc_第3页
Visual C++第06章 框架窗口、文档和视图.doc_第4页
Visual C++第06章 框架窗口、文档和视图.doc_第5页
已阅读5页,还剩78页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章 框架窗口、文档和视图尽管窗口、文档和视图是MFC的基础,但可能也是最不容易理解的部分,因为其概念比传统编程所需要的Windows函数更强一些,因此,须在本章做进一步详细讨论框架窗口、文档和视图的方法和技巧。6.1框架窗口 分两类:一是应用程序主窗口,另一类是文档窗口。6.1.1主窗口和文档窗口主窗口(或称主框架窗口)是应用程序直接放在桌面(DeskTop)上的那个窗口,每个应用程序只能有一个窗口,主窗口的标题栏上往往显示应用程序的名称。主窗口类的源文件名是MainFrm.h和MainFrm.cpp,其类名是CMainFrame。单文档SDI程序主窗口类是从CFrameWnd派生来的。多文档MDI程序主窗口类是从CMDIFrameWnd派生的。如果应用程序中还有工具栏(CToolBar)状态栏(CStatusBar),那么在CMainFrame类还含有表示工具栏和状态栏的成员变量m_wndToolBar和m_wndStatusBar,并在CMainFrame的OnCreate函数中进行初始化。文档窗口对于SDI程序来说,它和主窗口是一致的,即主窗口就是文档窗口;对于MDI程序,文档窗口是主窗口的子窗口。见书244页图6.1所示。文档窗口一般都有相应的可见边框,他的客户区(初了窗口标题栏、边框外的区域)是由相应的视图来构成的,可以说视图是文档窗口内的子窗口。文档窗口时刻跟踪当前处于活动状态的视图的变化,并将用户或系统产生的命令消息传递给当前活动视图。而主窗口负责管理各个用户交互对象(包括菜单、工具栏、状态栏以及加速键)并根据用户操作相应地创建或更新文档窗口及其视图。在MDI应用程序中,MFC AppWizard创建的文档子窗口类的源代码文件是ChildFrm.h和ChildFrm.cpp,其类名是CChildFrame,它是从CMDIChildWnd派生的。6.1.2窗口风格的设置窗口的风格决定了窗口的外观及功能,用户通过风格的设置增加或减少窗口中所包含的功能,这些功能一般都是由系统内部定义的,不需要用户去编程实现。 窗口风格可以通过MFC AppWizard来设置,也可以在主窗口或文档窗口类的PreCreateWindow函数中修改CREATESTRUCT结构,或是可以调用CWnd类的成员函数ModifyStyle和ModifyStyleEx来更改。1、 窗口风格通常以WS_为前缀和扩展以WS_EX_为前缀两种形式;这两种形式的窗口风格可在函数CWnd:Create(只能指定窗口的一般风格)或CWnd:CreateEx(可同时支持以上两种风格),对于控件和对话框这样的窗口来说,它们的窗口风格可直接通过其属性对话框来设置。常见的一般窗口风格如下所示:(书245页表6.1)WS_BORDER 窗口含有边框WS_CAPTION 窗口含有标题栏(它意味着还具有WS_BORDER风格) 但它不能和WS_DLGFRAME组合WS_CHILD 创建子窗口,它不能和WS_POPUP组合WS_CLIPCHILDREN 在父窗口范围内裁剪子窗口,它通常在父窗口创建时指定WS_CLIPSIBLINGS 裁剪相邻子窗口,也就是说,具有此风格的子窗口和其他子窗口重叠的部分被裁剪,它只和WS_CHILD组合WS_DISABLED 窗口最初时是禁用的WS_DLGFRAME 窗口含有双边框,但没有标题WS_GROUP 此风格被控件组中第1个控件窗口指定。用户可在控件组的第1个和最后1个控件中用方向键来选择WS_HSCROLL 窗口最初时处于最大化WS_MAXIMIZEBOX 在窗口的标题栏上含有”最大化”按钮WS_MINIMIZE 窗口最初处于最小化,他只和WS_OVERLAPPED组和WS_MINIMIZEBOX 在窗口的标题栏上含有”最小化”按钮WS_OVERLAPPED 创建覆盖窗口,一个覆盖窗口通常有一个标题和边框WS_OVERLAPPEDWINDOW 创建一含有WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU、WS_THICKFRAME、WS_MINIMIZEBOX和WS_MAXIMIZEBOX风格的覆盖窗口WS_POPUP 创建一弹出窗口,它不能和WS_CHILD组合,只能用 CreateWx函数指定WS_POPUPWINDOW 创建一含有WS_BORDER、WS_POPUP和WS_SYSMENU 风格的弹出窗口。当WS_CAPTION和WS_POPUPWINDOW 风格组合时才能使系统菜单可见。WS_SYSMENU 窗口的标题栏上含有系统菜单框,它仅用于含有标题的窗口WS_TABSTOP 用户可以用于TAB键选择控件组中的下一个控件WS_THICKFRAME 窗口含有边框,并可调整窗口的大小WS_VISIBLE 窗口最初是可见的WS_VSCROLL 窗口含有垂直滚动条除了这些风格外,框架窗口还有以下3个自己的风格。他们都可以在PreCreateWindow重载函数中指定。(1)FWS_ADDTOTITLE风格:指定一个文档名添加到框架窗口标题中,如书244页图6.1的“Ex_MDI-Ex_MDI1”的Ex_MDI1是文档名。若单文档应用程序,默认的文档名是”无标题”。(2)FWS_PREFIXTITLE风格:使得框架窗口标题中的文档名显示在应用程序名之前。例如,若未指定该风格时的窗口标题为”Ex_MDI_Ex_MDI1”,当指定该风格后就变成了”Ex_MDI1_Ex_MDI”。(3)FWS_SNAPTOBARS风格:用于调整窗口的大小,使它刚好包含了框架窗口中的控制栏(如工具栏)2、 用MFC AppWizard设置MFC AppWizard有一个Advanced(高级)按钮(在创建单或多文档程序时的第4步中),允许用户指定有关SDI和MDI框架窗口的属性。见书246页图6.2所示为”Advanced Options”对话框的Window Styles页面,其中的含义如下:(246页)(但在该对话框中,用户只能设定少数几种窗口风格)Use split window(应用拆分窗口) 选中时,将程序的文档窗口创建成”切分”*(或称拆分)窗口Thick frame(厚框) 选中时,设置窗口风格WS_THICKFRAMEMinimize box(最小化框符) 选中时,设置窗口风格WS_MINIMIZEBOXMaximize box(最大化框符) 选中时,设置窗口风格WS_MAXIMIZEBOXSystem menu(系统菜单) 选中时,设置窗口风格WS_SYSMENUMinimized(最小化) 选中时,设置窗口风格WS_MINIMIZEMaximized(最大化) 选中时,设置窗口风格WS_MAXIMIZE3、 修改CREATESTRUCT结构在窗口创建之前,系统自动调用PreCreateWindow虚函数。在MFC AppWizard创建SDI/MDI应用程序结构时,MFC已为主窗口或文档窗口类自动重载了该虚函数。我们可以在此函数中通过修改CREATESTRUCT结构来设置窗口的绝大多数风格。例:在SDI程序中,框架窗口默认的风格是WS_OVERLAPPEDWINDOW和FWS_ADDTOTITLE的组合,更改其风格。(1)建一个单文档的应用程序(2)在主框架程序MainFrm.cpp中找到PreCreateWindow虚函数,并加代码:BOOL CMainFrame:PreCreateWindow(CREATESTRUCT& cs)cs.style&=WS_MAXIMIZEBOX;/新窗口不带有最大化按钮cs.cy=:GetSystemMetrics(SM_CYSCREEN)/3; cs.cx=:GetSystemMetrics(SM_CYSCREEN)/3;/将窗口大小设置为1/3屏幕大/小,并居中。cs.y=(cs.cy*3)-cs.cy)/2;cs.x=(cs.cx*3)-cs.cx)/2;/调用基类的PreCreateWindow(cs)函数 return CFrameWnd:PreCreateWindow(cs);/if( !CFrameWnd:PreCreateWindow(cs) )/return FALSE;/ TODO: Modify the Window class or styles here by modifying/ the CREATESTRUCT cs/return TRUE;(3)编译运行,见出现的窗口是原来的1/3。(4)建一个多文档MDI应用程序(先运行一下试一试窗口最大化按钮)(5)在子文档窗口ChildFrm程序中找到PreCreateWindow虚函数,并加代码:(创建不含有最大化按钮的子窗口)BOOL CChildFrame:PreCreateWindow(CREATESTRUCT& cs)/ TODO: Modify the Window class or styles here by modifying/ the CREATESTRUCT cs cs.style&=WS_MAXIMIZEBOX;/创建不含有最大化按钮的子窗口return CFrameWnd:PreCreateWindow(cs);/if( !CMDIChildWnd:PreCreateWindow(cs) )/return FALSE;/return TRUE;结果是:不含有最大化按钮的子窗口代码中,前面有“:”作用域符号的函数是指全局函数。代码“cs.style &=WS_MAXIMIZEBOX;”中的“”是按位取“反”运算符,它将WS_MAXIMIZEBOX的值按位取反后,再和cs.style值按位“与”,其结果是将cs.style值中的WS_MAXIMIZEBOX标志位清零。4、 使用ModifyStyle和ModifyStyleExCWnd类中的成员函数ModifyStyle和ModifyStyleEx也可用来更改窗口的风格,其中ModifyStyleEx还可更改窗口的扩展风格。这两个函数具有相同的参数:BOOL ModifyXXXX(DWORD dwRemove,DWORD dwAdd,UINT nFlags=0);参数:dwRemove用来指定需要删除的风格 dwAdd 用来指定需要增加的风格 nFlags 表示SetWindowPos的标志,0(默认)表示更改风格的同时不 调用SetWindowPos函数由于框架窗口在创建时不能直接设定其扩展风格,因此只能通过调用ModifyStyle函数来进行。例:在多文档(MDI)的子文档窗口增加水平和垂直滚动条(书247页例,248页图6.3)(1)用MFC AppWizard创建一个多文档应用程序(或用上个多文档应用程序),名为:“多文档”(2)用ClassWizard为子文档窗口类CChildFrame添加OnCreateClient处理消息:ViewClassWizardCChildFrameOnCreateClientAdd FunctionEdit Code并加如下代码:BOOL CChildFrame:OnCreateClient(LPCREATESTRUCT lpcs,,CCreateContext* pContext) / TODO: Add your specialized code here and/or call the base classModifyStyle(0,WS_VSCROLL,0);/垂直滚动轴 ModifyStyle(0,WS_HSCROLL,0);/水平滚动轴return CMDIChildWnd:OnCreateClient(lpcs, pContext);(3)编译并运行(书上只有一个滚动轴)6.1.3窗口状态的改变 MFC AppWizard为每个窗口设置了相应的大小和位置,但总有的默认窗口不另人满意,这时就需要进行适当的调整。1、用ShowWindow改变窗口的显示状态 当应用程序运行时,Windows会自动调用应用程序框架内部的WinMain函数,并自动查找该应用程序类的全局变量theApp,然后自动调用用户应用程序类的虚函数InitInstance,该函数会进一步调用相应的函数来完成主窗口的构造和显示工作,如一个单文档应用程序的应用程序文件中的程序名.cpp中的InitInstance()函数中的代码:m_pMainWnd-ShowWindow(SW_SHOW);m_pMainWnd-UpdateWindow();参数:SW_SHOW是用当前的大小和位置激活并显示窗口。 m_pMainWnd是主框架窗口指针变量,ShowWindow是CWnd类的成员函数,用于按指定的参数显示窗口,该参数的值如下:SW_HIDE 隐藏此窗口并将激活状态移交给其他窗口SW_MINIMIZE 将窗口最小化并激活系统中的顶层窗口SW_RESTORE 激活并显示窗口。若窗口是最小或最大状态时,则恢复到原来的大小和位置SW_SHOW 用当前的大小和位置激活并显示窗口SW_SHOWMAXIMIZED 激活窗口并使之最大化SW_SHOWMINIMIZED 激活窗口并使之最小化SW_SHOWMINNOACTIVE窗口显示成为一个图标并保留其激活状态(即原来是激活的,仍然是激活)SW_SHOWNA 用当前状态显示窗口SW_SHOWNOACTIVATE 用最近的大小和位置状态显示窗口并保留其激活状态SW_SHOWNORMAL 激活并显示窗口 通过指定ShowWindow函数的参数值可以改变窗口显示状态,例如:将窗口的初始状态设置为”最小化”,可以这样写:m_pMainWnd-ShowWindow(SW_SHOWMINIMIZED);m_pMainWnd-UpdateWindow(); 由于用户应用程序类继承了基类CWinApp的特性,因此也可在用户应用程序类CWinApp中使用公有型(public)成员变量m_nCmdShow,通过对其进行赋值,同样能达到效果。例如:在上个“多文档”项目的应用程序的InitInstance()函数中这样写:m_nCmdShow=SW_SHOWMAXIMIZED;/激活窗口并使之最大化,书是最小pMainFrame-ShowWindow(m_nCmdShow);pMainFrame-UpdateWindow();return TRUE;2、 用SetWindowPos或MoveWindow改变窗口的大小和位置CWnd中的SetWindowPos是一个非常有用的函数,它不仅可以改变窗口的大小、位置,而且还可以改变所有窗口在堆栈排列的次序(Z次序),这个次序是根据它们在屏幕出现的先后来确定的。BOOL SetWindowPos(const CWnd *pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);参数:pWndInsertAfter表示窗口对象指针,它可以预定义下列窗口对象的地址: wndBottom将窗口放置在Z次序中的底层 wndTop将窗口放置在Z次序中的顶层 wndTopMost设置最顶层窗口 wndNoTopMost将窗口放置在所有最顶层的后面,若此窗口不是最顶窗口,则此标志无效。 x和y表示窗口新的左上角坐标,cx和cy分别表示窗口的宽度和高度, nFlags表示窗口新的大小和位置方式,如下说明(书250页表6.4)常用nFlags值及其含义:SWP_HIDEWINDOW隐藏窗口SWP_NOACTIVATE 不激活窗口。如该标志没有被指定,则依赖pWndInsertAfter参数SWP_NOMOVE 不改变当前的窗口位置(忽略x和y参数)SWP_NOOWNERZORDER不改变父窗口的Z次序SWP_NOREDRAW 不重新绘制窗口SWP_NOSIZE 不改变当前的窗口大小(忽略cx和cy参数)SWP_NOZORDER 不改变当前的窗口Z次序(忽略pWndInsertAfter参数)SWP_SHOWWINDOW 显示窗口函数CWnd:MoveWindow也可用来改变窗口的大小和位置,与SetWindowPos函数不同的是,用户必须在MoveWindow函数中指定窗口的大小。void MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint=TRUE);void MoveWindow(LPCRECT lpRect,BOOL bRepaint=TRUE);参数:x,y表示窗口新的左上角坐标nWidth,nHeight表示窗口新的宽度和高度bRepaint用于指定窗口是否重绘lpRect表示窗口新的大小和位置例:用上面两个函数,把主窗口移到屏幕的(100,100)处。(1)建一个单文档的应用程序(2)打开:文件名.cpp应用程序,找到BOOL CMyApp:InitInstance()函数,并添下列代码: m_pMainWnd-SetWindowPos(NULL,100,100,0,0,SWP_NOSIZE|SWP_NOZORDER);/不改变当前的窗口大小和窗口Z次序, CRect rcWindow; /见上面说明(书250页表6.4) m_pMainWnd-GetWindowRect(rcWindow); m_pMainWnd-MoveWindow(100,100,rcWindow.Width(),rcWindow.Height(),TRUE);/改变窗口位置/AfxGetMainWnd()-CenterWindow();/将主框架窗口居中./AfxGetMainWnd()-CenterWindow(CWnd:GetDesktopWindow();/将窗口置于屏幕中央/return TRUE; 当然,改变窗口的大小和位置的CWnd成员函数还不止以上两个,例如:CenterWindow(CWND:GetDesktopWindow())函数是使窗口居于父窗口(屏幕)中央。AfxGetMainWnd()-CenterWindow();/将主框架窗口居中。见上面已加上的两个函数。6. 2文档模板 用MFC AppWizard创建的单文档(SDI)或多文档(MDI)应用程序均包含应用程序类、文档类、视图类和框架窗口类,这些类是通过文档模板有机地联系在一起的。6.2.1文档模板类 文档应用程序框架结构是在程序运行一开始构造的。1、在单文档应用程序的应用程序类InitInstance()函数中,可以看到这样的代码:BOOL CMyApp:InitInstance()CSingleDocTemplate *pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME, /资源IDRUNTIME_CLASS(CMyDoc), /(以中文名字命名的项目名的项目)文档类RUNTIME_CLASS(CMainFrame),/ 主框架窗口类RUNTIME_CLASS(CMyView) /(以中文名字命名的项目名的项目)视图类);AddDocTemplate(pDocTemplate);.return TRUE; 代码中:pDocTemplate 是类CSingleDocTemplate的指针对象。CSingleDocTemplate是一个单文档模板类,他的构造函数中有4个参数,分别表示菜单和加速键等的资源ID号以及3个由宏RUNTIME_CLASS指定的运行时类对象。AddDocTemplate 是类CWinApp的一个成员函数,当调用了该函数后,就建立了应用程序类、文档类、视图类和主框架类之间的相互联系。2、在多文档应用程序的应用程序类InitInstance()函数中,同样可以看到这样的代码: BOOL CMyApp:InitInstance() CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate( IDR_MYTYPE, /(以中文名字命名的项目名的项目)资源ID号 RUNTIME_CLASS(CMyDoc),/(以中文名字命名的项目名的项目)文档类 RUNTIME_CLASS(CChildFrame),/ MDI文档窗口类 RUNTIME_CLASS(CMyView)/(以中文名字命名的项目名的项目)视图类);AddDocTemplate(pDocTemplate);/ create main MDI Frame window创建主框架窗口CMainFrame* pMainFrame = new CMainFrame;if (!pMainFrame-LoadFrame(IDR_MAINFRAME)return FALSE;m_pMainWnd = pMainFrame;Return TRUE;由于多文档模板是用于建立资源、文档类、视图类和子框架窗口(文档窗口)类之间的联系的,因而多文档的主框架窗口需要额外的代码来创建。代码中:LoadFrame()是CFrameWnd类成员函数,用于加载与主框架窗口相关的菜单、加速键、图标等资源。说明:多文档主框架窗口的创建应在多文档模板创建后进行,以便MFC程序框架将多文档模板和多文档主框架窗口建立联系。 应用程序类对象在模板被创建之前就已经存在,但此时文档、视图及框架对象还没有被创建。程序运行后,程序框架会动态地创建这些对象。这一动态创建的过程包含了对C+语言的非常复杂的运用。 通过在用户文档类、视图类以及主框架类的定义(.h)及实现(.cpp)过程中使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,MFC库可以动态地创建相应的类对象。 这种称为运行时类的动态创建机制,简化了程序员编程工作,拓展了“类”的功能,是MFC程序框架结构的重要特性。6.2.2 文档模板字串资源 在MFC AppWizard创建的应用程序资源中,许多资源标识符都是IDR_MAINFRAME意味着这些具有同名标识的资源将被框架自动加载到应用程序中。其中String Table(字符串)资源列表中也有一个IDR_MAINFRAME项,他是用于标识文档类型、标题等内容的,称为“文档模板字串资源”。其内容如下(以单文档“模板”为例)模板nnMynnnMy.DocumentnMy Document可以看出,IDR_MAINFRAME所标识的字符串被分成了一些以“n”结尾的子串,这些子串共有7段,每段都有特定的用途,如:(252页表6.5) 文档模板字符串的含义:IDR_MAINFRAME的子串 串号 用途模板n 0 应用程序窗口标题即窗口标题栏:无标题-模板 n 1 文档根名。对多文档应用程序来说,若在文档窗口标题上显示“Sheet1”,则其中的Sheet就是文档根名,若该子串为空,则文档名为默认的“无标题”Myn 2 新建文档的类型名。若有多个文档类型,则这个名称将出现在“新建”对话框中n 3 通用对话框的文件过滤器正文n 4 通用对话框的文件扩展名My.Documentn 5 在注册表中登记的文档类型标识My Document 6 在注册表中登记的文档类型名称但对于MDI(多文档)来说,上述的字串分别由IDR_MAINFRAME和IDR_MYTYPE(项目名为:中文名:“字串资源“)2项组成;其中,IDR_MAINFRAME表示窗口标题,而IDR_MYTYPE表示后6项内容。它们的内容如下:IDR_MAINFRAME: My(中文项目名)IDR_MYTYPE: nMynnnMy.DocumentnMy Document 实际上,文档模板字串资源内容既可直接通过字串资源编辑器进行修改,也可以在文档应用程序中创建向导的第4步中,通过“Advanced Options”对话框中的“Document Template String”页面来指定,如书235页图6.4所示(名字是Ex_SDI)。图中的数字表示该项的含义与上表中对应串号的含义相同。6.2.3使用多个文档类型 在MFC AppWizard创建的应用程序中,通常只有一种文档类型。但有时,用户也需要另一种文档类型。例如Visual C+6.0本身既要处理文本文件,也要处理MFC资源,至少要有2种文档类型。 多种文档类型的应用程序中一般有多个文档模板、多个文档类以及与之紧密相联的多个视图类。 当用户选择“文件”菜单的“新建”命令时,应用框架将弹出含有文档类型列表的对话框,允许用户自己选择所需的文档类型。下面是实现在多文档应用应用程序中使用多种文档类型。例:使用多个文档(1)用MFC AppWizard创建一个多文档应用程序(Step1第一步就单击Finish即可)(2)(3)“多个文档类型实例”(4)nPicturenMyDenmo图片n图片文件(*.bmp)n.bmpnMyDemo.Documentn My Document(5)在“字符串属性”对话框中将ID设为IDR_OTHERTYPE=130,标题内容设为:nTxtnMyDemo 文本n 文本文件(*.txt,*.cpp,*.h)n.txt;*.cpp,*.hnMyDemo.Documentn MyDocument(6)COtherDoc(7)COtherDoc(8)pDocTemplate=new CMultiDocTemplate(IDR_OTHERTYPE,RUNTIME_CLASS(COtherDoc),/指定新的文档类 RUNTIME_CLASS(CChildFrame),RUNTIME_CLASS(COtherView);/指定新的视图类AddDocTemplate(pDocTemplate);(9) #include OtherDoc.h#include OtherView.h(10)运行结果见书说明:A、如果在该例程序中再添加图标和菜单资源,并使资源标识设为IDR_OTHERTYPE 则当创建“MyDemo文本”文档类型后,程序会自动使用新的图标和菜单资源。 B、单文档应用程序也可以有多个文档类型,它的实现方法与多文档类似,也是通过添加文档模板来实现的,只不过每次只能在文档窗口(视图)中显示一个文档。6.3文档序列化 用户处理的数据往往需要存盘作为永久备份。将文档类中的数据成员变量的值保存在磁盘文件中,或者将存储的文档文件中的数据读取到相应的成员变量中,这个过程称为序列化(Serialize)。6.3.1文档序列化过程 在使用MFC程序结构进行文档序列化之前,我们先了解对文档不同操作的具体程序运行过程。1创建空文档(256页有说明)应用程序类的InitInstance函数在调用了AddDocTemplate函数之后,会通过CWinApp:ProcessShellCommand间接调用CWinApp的另一个非常有用的成员函数OnFileNew,并依次完成文档各个步骤的创建。.2)打开文档当MFC AppWizard创建应用程序时,它会自动将“文件(File)”选单中的“打开(Open)”命令(ID号为ID_FILE_OPEN)映射到CWinApp的OnFileOpen成员函数。这一结果可以从应用类(.cpp)的消息入口处得到验证:见书257页除了使用“文件(File)”“打开(Open)”选项外,用户也可以选择最近使用过的文件列表来打开相应的文档。在应用程序的运行过程中,系统会记录下4个(默认)最近使用过的文件,并将文件名保存在Windows的注册表中。当每次启动应用程序时,应用程序都会在“文件(File)”选单中显示最近使用过的文件名称。需要说明的是:MFC为我们重载了Serialize函数,不必使用CFile类就可以完成相应的文档操作。(写磁盘和串口访问这样这样的任务)例:使用Serialize函数,读取文档中的数据(附加)(1)打开前面的“多文档”应用程序或重新建一个单或多文档应用程序。(2)加成员变量工作区ClassView右键对准CMyDoc单击Add Member Variable右键 单击出现对话框Variable Type处写:char Variable Name处写:m_ch300 在文档类中加了一个成员变量。(3)在文档类即多文档Doc.cpp中找到:void CMyDoc:Serialize(CArchive& ar) 函数并加代码: void CMyDoc:Serialize(CArchive& ar)/CArchive的对象是ar(引用)if (ar.IsStoring()/ TODO: add storing code hereelse/ TODO: add loading code herefor(int i=0;im_chi;CString str;str.Format(_T(%s),m_ch);AfxMessageBox(str);这样,当我们通过选单的“打开(Open)”成功打开(用*.*)一个文件时,将弹出一个对话框,显示出该文件的前300个字符的内容。3)保存文档(257页)当MFC AppWizard创建应用程序时,它会自动将“文件(File)”选单中的“保存(Save)”命令与文档类CDocument的OnFileSave函数在内部关联起来,但用户在程序框架中看不到相应的代码。OnFileSave函数还会进一步完成下列工作。(1) 弹出通用文件“保存”对话框,让用户提供一个文件名(2) 调用文档对象的CDocument:OnSaveDocument虚函数,接着又自动调用Serialize函数,将CArchive对象的内容保存在文档中。说明:A、 只有在保存文档之前还没有存过盘(即没有文件名)或读取的文档是“只读”的,OnFileSave函数才会弹出通用“保存”对话框,否则只执行第2步。B、“文件(File)”菜单中还有一个“另存为(Save As)”命令,它是与文档类CDocument的OnFileSaveAs函数相关联。不管文档有没有保存过,OnFileSaveAs都会执行上述2个步骤。C、上述文档存盘的必要操作都是由系统自动完成的。除了系统自动将文档存盘外,用户可以用ClassWizard来重载CDocument:OnSaveDocument函数,并可在Serialize()函数体的ar.IsStorinr()为“真”的条件语句处添加代码,从而在文档中保存用户自己的数据。例:使用Serialize函数,保存文档中的数据(附加)(1)打开前面的“多文档”应用程序或重新建一个单或多文档应用程序。(2)如果是重建的应用程序,也按前面第二步在文档类CMyDoc中加一个成员变量char m_ch300。(3)在文档类即多文档Doc.cpp中找到:void CMyDoc:Serialize(CArchive& ar) 函数并加代码:void CMyDoc:Serialize(CArchive& ar)/ CArchive的对象是ar(引用)if (ar.IsStoring()/ TODO: add storing code herefor(int i=0;isizeof(m_ch);i+)arm_chi;else/ TODO: add loading code herefor(int i=0;im_chi;CString str;str.Format(_T(%s),m_ch);AfxMessageBox(str);上述代码的结果是当保存的文件名成功指定后,该文件保存m_ch中的300字符。若文件中有其它数据,则数据被自动清除。(可用Word随便建个文件名“小山”,先打开一个文件,成功后,再用保存,将刚才打开的文件另存为“小山”,退出再运行之后打开小山,就是刚才打开的文件内容)4、关闭文档当用户试图关闭文档(或退出应用程序)时,应用程序会根据用户对文档的修改与否来进一步完成下列任务。(1)若文档内容已被修改,则弹出一个“消息”对话框,询问用户是否需要将文档保存。当用户选择“是”,则应用程序执行OnFileSave过程。(2)调用CDocument:OnCloseDocument虚函数,关闭所有与该文档相关联的文档窗口及相应的试图,调用文档类CDocument的DeleteContents清除文档数据。MFC应用程序通过CDocument的protected类型成员变量m_bModified的逻辑值来判断用户是否对文档进行修改,如果m_bModified为“真”,则表示文档被修改。对于用户来说,可以通过CDocument的SetModifiedFlag成员函数来设置或通过IsModified成员函数来访问m_bModified的逻辑值。当文档创建、从磁盘中读出以及文档存盘时,文档的这个标记就被置为FLASE(假);而当文档数据被修改时,用户必须使用SetModifiedFlag函数将该标记置为TRUE。这样,当用户关闭文档时,应用程序才会显示询问消息对话框。(多文档与单文档类似)。6.3.2文档序列化操作 打开和保存文档,系统都会自动调用Serialize函数。而MFC AppWizard在创建文档应用程序框架时已在文档类中重载了Serialize函数,通过在该函数中加代码可达到实现数据序列化的目的。例如:上面的“打开”“保存”都在Serialize里加了代码。void CMyDoc:Serialize(CArchive& ar)if (ar.IsStoring()/ TODO: add storing code hereelse/ TODO: add loading code here 代码中,Serialize函数的参数ar是一个CArchive类引用变量。通过判断ar.IsStoring的结果是“真”还是“假”就可决定向文档写或读数据。 CArchive(归档)类提供对文件数据进行缓存,同时还保存一个内部标记,用于标识文档是存入(写盘)还是载入(读盘)。每次只能有一个活动的存档与ar相连。通过CArchive类可以简化文件操作,提供“”运算符,用于向文件写入简单的数据类型以及从文件中读取它们。下面是CArchive支持的常用数据类型:类 型 描 述 类 型 描 述BYTE 8位无符号整型 WORD 16位无符号整型LONG 32位带符号整型 DWORD 32位无符号整型float 单精度浮点 double 双精度浮点int 带符号整型 short 带符号短整型char 字符型 unsigned 无符号整型除了“”运算符外,CArchive类还提供成员函数ReadString和WriteString用于从一个文件对象中读、写一行文本,它们的原型如下:BOOL ReadString(CString &rString);LPTSTR ReadString(LPTSTR lpsz,UINT nMax);void WriteString(LPCTSTR lpsz);其中,lpsz用于指定读或写的文本内容,nMax用于指定可以读出的最大字符个数。注意:当向一个文件写一行字符串时,字符0和n都不会写到文件中。 CArchive(归档)类:CArchive类没有基类,它提供了串行化对象从文件中读写的类型安全缓冲机制,可以把CArchive对象想象成一种二进制流,就象输入/输出流一样可以顺序高效的处理二进制对象数据。使用CArchive对象之前,必须先创建一个CFile对象,同时保证CArchive对象的读写标志设置和文件打开方式相一致。对于一个CArchive对象,可以进行存储操作,也可以读取,但不能2者同时进行。(1)CArchive类操作符” CArchive对象的引用,类似于流的输入/输出(cin/cout),可以使用一系列的操作符以简化程序,例如:int x; CString y; arxy;ar是CArchive类的对象,见Serialize(CArchive &ar)函数2、CArchive类的成员函数:Read()、Write() 读写指定字节数的缓冲区内容ReadString()、WriteString()读写一行文本ReadObject()、WriteObject()调用一个对象的Serialize函数来读或写ReadClass()、WriteClass()读写一个CRuntimeClass指明对象IsLoading()、IsStoring()判断当前读写状态3、Serialize()函数 在”MFC AppWizard”自动生成的程序框架中,文件的串行化操作都是由CDocument派生类成员函数Serialize()完成的。它的结构如下:void CMySdiDoc:Serialize(CArchive &ar) if(ar.IsStoring() /TODO:.else /TODO 在这个成员函数中,使用CArchive对象完成具体的操作。参数中传递进来的CArchive引用对象(ar),是由MFC程序框架根据用户输入需要执行串行化操作时创建的,它包含了所需要的文件的信息,使用它可以对各种CArchive类支持的数据格式进行读写、调用其它CObject派生类对象的串行化函数等。 “MFC AppWizard

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论