VC第三章,MFC框架之文档与视图.ppt

上传人:sccc 文档编号:5074283 上传时间:2023-06-02 格式:PPT 页数:44 大小:429.05KB
返回 下载 相关 举报
VC第三章,MFC框架之文档与视图.ppt_第1页
第1页 / 共44页
VC第三章,MFC框架之文档与视图.ppt_第2页
第2页 / 共44页
VC第三章,MFC框架之文档与视图.ppt_第3页
第3页 / 共44页
VC第三章,MFC框架之文档与视图.ppt_第4页
第4页 / 共44页
VC第三章,MFC框架之文档与视图.ppt_第5页
第5页 / 共44页
点击查看更多>>
资源描述

《VC第三章,MFC框架之文档与视图.ppt》由会员分享,可在线阅读,更多相关《VC第三章,MFC框架之文档与视图.ppt(44页珍藏版)》请在三一办公上搜索。

1、第三章 MFC框架之文档与视图,本章内容,MFC应用程序的开发流程AppWizard生成的文件类型ClassWizard的功能与应用初步用户工程中“文档与视图结构”菜单设计及应用鼠标消息的处理工具栏与状态栏设计文档的读写滚动视图与多视图,一、MFC应用程序的开发流程创建一个应用程序框架为新工程添加必要的资源,如菜单、对话框按程序功能要求,为其添加新类及其类成员编写类的成员函数的实现代码编译、链接,修改错误,生成EXE文件运行并测试新程序,修正设计缺陷将程序由调试版升级为正式发行版,MFC应用程序开发流程图,二、AppWizard生成的文件类型,MFC中资源标识符前缀,三、ClassWizard

2、的功能与应用初步1、应用程序类的继承关系示意图,2、类的命名规则class Name=C+projectName+classType,3、classWizard的功能创建新类把消息映射为类的成员函数新建或删除消息处理函数察看已被处理的消息并跳到消息处理代码处定义成员变量创建新类时,自动加入方法和属性处理现有的类和类库,4、classWizard的应用实例:编写一个SDI程序框架,并实现在视图区以信息对话框的形式显示用户点击鼠标左、右键和次数。为视图类添加m_nLeft、m_nRight两个私有型变量,并在构造函数中对其初始化;利用类向导在视图类中为鼠标左右单击操作添加“消息处理函数”OnLBu

3、ttonDown()和OnRButtonDown();为OnLButtonDown()函数添加功能代码,右键函数与此类似m_nLeft+;CString strOutput;strOutput.Format(“鼠标左键单击的次数为:%d”,m_nLeft);MessageBox(strOutput);编译、链接并运行程序,测试程序效果。,2、MFC的文档/视图结构采用分离机制将数据的管理和显示分作两部分,数据管理和维护由文档负责,数据的显示和编辑由视图负责。,文档/视图结构是MFC的一大特色:把数据处理类从用户界面处理类中分离出来,使每一个类专门完成指定的任务。APP向导已经设计好了两者间的相

4、互关系,程序员只要把主要精力放在具体的数据结构设计和数据显示操作上即可。,3、文档/视图的相互作用函数(1)视图类的GetDocument()函数(2)文档类的UpdateAllViews()函数(3)视图类的OnUpdate()函数,支持文档/视图相互作用的函数还有:OnInitialUpdate()OnNewDocument()实际上,刷新视图的一般过程是:CDocument:UpdateAllViews()CView:OnUpdate()CView:Invalidate()OnPaint()OnDraw(),4、多文档MFC多文档应用程序与单文档程序的根本差别MDI窗口类的派生关系如下:

5、CMDIFrameWnd:CMainFrame主框架窗口类;CMDIChildWnd:CChildFrame子框架窗口类;文档模板描述了对应于每一种类型文档的视图和窗口的类型,由其来确立文档、视图、框架和各种资源之间的固定关系。,SDI和MDI文档模板的样式:文档模板是在APP类的初始化函数InitInstance()中声明。CSingleDocTemplate*pDocTemplate;pDocTemplate=new CSingleDocTemplate(/单文档模板IDR_MAINFRAME,/主框架资源的IDRUNTIME_CLASS(CMySDIDoc),/SDI文档类RUNTIME

6、_CLASS(CMainFrame),/SDI主框架窗口类RUNTIME_CLASS(CMySDIView);/SDI视图类AddDocTemplate(pDocTemplate);/CMultiDocTemplate*pDocTemplate;pDocTemplate=new CMultiDocTemplate(IDR_MYMDITYPE,/子框架窗口资源IDRUNTIME_CLASS(CMyMDIDoc),RUNTIME_CLASS(CChildFrame),/MDI子框架窗口类RUNTIME_CLASS(CMyMDIView);AddDocTemplate(pDocTemplate);,

7、五、菜单设计及应用1、建立菜单资源实例:创建一个名为DrawCoin的SDI项目,添加“画硬币”主菜单,并增加两个菜单项“增加硬币”、“减少硬币”。编程:(1)添加顶层菜单“画硬币(&C)”(2)增加两个菜单项(Menu Item)ID_COIN_ADD 增加硬币(&A)tCtrl+A 在客户区增加一枚硬币n增币ID_COIN_SUB 减少硬币(&S)tCtrl+S 在客户区减少一枚硬币n减币,2、添加菜单命令的处理函数菜单实则一系列命令的列表,当某一菜单项被点击后,一个含有该菜单项ID标识的WM_COMMAND命令消息将发送给APP窗口,APP将该消息转换为一个“命令消息处理函数”的函数调用

8、,从而响应命令。利用“类向导”(Ctrl+W)工具为菜单添加消息映射函数,并添加用户代码:,本例中,为了实现菜单的操作功能,还必须完成如下三步:(1)为文档类添加一个名为m_nCoins的公有型整型变量;(2)利用类向导工具为文档类添加名为“DeleteContents”的消息处理函数,并在其内对m_nCoins=1初始化。该函数在用户重新使用一个文档时自动调用。(3)修改视图类的OnDraw()函数,根据文档类保存的m_nCoins当前值画出指定数量的硬币for(int i=0;im_nCoins;i+)int y=200-10*i;pDC-Ellipse(200,y,300,y-30);p

9、DC-Ellipse(200,y-10,300,y-35);/用两个上下偏移椭圆表示硬币,UPDATE_COMMAND_UI是“更新用户界面命令消息”:它能够根据程序当前运行状态来动态设置菜单项的状态(可用或不可用)。在程序刚运行时,将菜单项“减少硬币”置为“不可用”(灰显状态)。需要在其UPDATE_COMMAND_UI消息映射函数中,添加代码:if(m_nCoinsEnable(FALSE);/禁用菜单项(灰显)elsepCmdUI-Enable(TRUE);/使能菜单项(正常显示),3、为菜单命令设置加速键在资源视图Accelerator中IDR_MAINFRAME项的加速键列表最后一空

10、行操作。,4、为新菜单添加“弹出式快捷菜单”利用类向导为视图类添加WM_CONTEXTMENU消息处理函数,并添加如下代码:CMenu menuPopup;/声明菜单对象if(menuPopup.CreatePopupMenu()/创建菜单menuPopup.AppendMenu(MF_STRING,ID_COIN_ADD,”增加硬币tCtrl+A”);/向菜单中添加菜单项menuPopup.AppendMenu(MF_STRING,ID_COIN_SUB,”减少硬币tCtrl+M”);/向菜单中添加菜单项/显示弹出式菜单,并对用户选择做出响应menuPopup.TrackPopupMenu(

11、TPM_LEFTALIGN,point.x,point.y,this);,六、鼠标消息的处理1、鼠标消息的类型WM_MOUSEMOVE(移动);WM_LBUTTONDBLCLK(双击左键);WM_LBUTTONDOWN(按下左键);WM_LBUTTONUP(释放左键);WM_RBUTTONDOWN(按下右键);WM_RBUTTONUP(释放右键);(1)客户区鼠标消息(最常见)(2)非客户区鼠标消息(相对少见),2、鼠标消息的应用举例实例:编写一个SDI程序MyDraw,程序运行后,当用户在客户区内按下鼠标左键并移动时,会沿鼠标移动轨迹自动绘制出连续的线段。分析:本例属典型的“客户区鼠标消息”

12、的应用。编程实现:(具体步骤及代码详见MyDraw.txt文件),七、工具栏与状态栏设计1、添加工具栏按钮的方法工具栏是由形象化的位图按钮所组成,它结合了菜单和快捷键的共同优点,具有操作直观快捷,使用方便的特点。工具栏内的按钮一般都与某一特定的菜单命令相对应,从功能上讲,它与特定菜单命令一致。在具体编程实现上,程序员应当先利用资源视图设计出新按钮图形图标,后将其ID值设置成与对应菜单项ID相同即可。实例:为前述的DrawCoins程序的工具栏添加两个对应按钮.,2、添加用户自定义工具栏的方法添加用户自定义工具栏步骤:(1)在工程中插入新工具条资源,并添加相关按钮;(2)在CMainFrame类

13、头文件中加入:CToolBar my_ToolBar;(3)在MainFrame.cpp文件的Create()函数中模仿生成标准工具栏的方法,书写生成新工具栏的语句,并在最后“停泊工具栏”的函数中加入第2个参数AFX_IDW_DOCKBAR_LEFT;(4)为工具条的各个按钮添加UPDATE_COMMAND_UI和COMMAND类型的消息映射,并添加实现代码;(5)在”查看”菜单中为新工具条的添加控制菜单命令;在消息映射处理函数中以 IsWindowVisible()函数为判断条件,以ShowWindow()函数的SW_HIDE或SW_SHOW参数控制,以决定其显隐。,实例:为MyDraw画线

14、程序添加“画笔选择”工具栏(该例以另一种方式实现工具栏按钮的基本功能).(1)在视图类中头文件中手工添加工具条的消息映射函数的声明:afx_msg void OnPenChioce(UINT nID);(2)在实现文件中加入消息映射宏:ON_COMMAND_RANGE(ID_PEN_RED,ID_PEN_WIDTH,OnPenChioce)(3)在实现文件中加入消息处理函数的定义:void CMyDrawView:OnPenChioce(UINT nID)switch(nID)/以下case语句分别对应于画笔工具条自左向右的各个按钮控件case ID_PEN_RED:m_colors=RGB(

15、255,0,0);break;/红笔取色case ID_PEN_SOLID:PenStyle=PS_SOLID;break;/设置画笔风格为实线case ID_PEN_WIDTH:PenWidthDlg();break;/调用自定义函数获取笔粗数据default:break;Pen.DeleteObject();Pen.CreatePen(PenStyle,PenWidth,m_colors);/创建画笔(4)为工具条的某些按钮继续书写函数功能定义代码,如PenWidthDlg(),3、定制状态栏状态栏是位于主窗口底部,用于显示当前操作提示信息和键盘状态的长条型子窗口,一般由状态信息行和状态指

16、示器两部分组成。前者用于动态地显示APP串表资源中的字符串,后者用于显示键盘的状态信息。通常,MFC程序将状态条自左向右分成4个窗格:(1)窗格显示菜单或工具栏的提示信息;(2)窗格显示键盘的大小写状态;(3)窗格显示数字键盘状态;(4)窗格显示键盘的Scroll Lock状态。,在MainFrame.cpp文件中,StatusBar由一个静态数组来定义:Static UINT indicators=ID_SEPARATOR,/定义分隔符,作为提示信息行的面板标识ID_INDICATOR_CAPS,/大小写指示器面板标识ID_INDICATOR_NUM,/数字指示器面板标识ID_INDICAT

17、OR_SCRL,/滚动指示器面板标识;CStatusBar类有两个重要函数:SetPaneText()用于在指定窗格上显示字符信息,SetPaneInfo()可改变一个指示器面板的ID、风格和宽度。,实例:修改前述DrawCoins程序的状态栏,使其能动态显示硬币数目。(1)在“String Table”中加入新的字符串信息,其ID为ID_INDICATOR_COINS,Caption为”硬币数目”。(2)在Mainframe.cpp中修改indicators 数组:Static UINT indicators=ID_SEPARATOR,/定义分隔符,作为提示信息行的面板标识ID_INDICA

18、TOR_COINS,/新添加一个指示器面板标识ID_INDICATOR_CAPS,/大小写指示器面板标识ID_INDICATOR_NUM,/数字指示器面板标识ID_INDICATOR_SCRL,/滚动指示器面板标识;(3)在视图类的OnDraw()函数中定制状态栏新窗格的显示信息,在OnDraw()函数中添加如下代码:CString strCoins;/声明状态栏新窗格的字符串变量CStatusBar*pStatus=(CStatusBar*)AfxGetApp()-m_pMainWnd-GetDescendantWindow(ID_VIEW_STATUS_BAR);/状态栏指针if(pSta

19、tus)strCoins.Format(当前硬币个数:%d,pDoc-m_nCoins);pStatus-SetPaneInfo(1,1,NULL,98);/指定序号窗格的宽度pStatus-SetPaneText(1,strCoins);/在指定窗格显示硬币个数编译并运行,检验正误。,八、文档的读写在MFC中,CFile类专门用于处理文件,使用它,需要在程序中包含afx.h的头文件,而且还需要对工程进行特定设置,即Project|SettingsLink标签页MFC项Use MFC in a Dll or Static Library。使用该类的缺点在于打开或读写文件时可能发生异常情况,需要

20、进行复杂的异常处理。对于二进制文件来说,MFC使用“序列化”简化了文件的读写操作。,1、序列化(Serialize)持久性是指对象所具有的保存和加载其状态的能力,在程序运行结束之前通过将对象的当前状态写入永久性存储体中,在下次再运行时通过数据的读取而恢复对象的状态。在MFC所支持的APP框架程序中,对象的保存和恢复的过程就称为“序列化”。在利用APP向导生成文档/视图结构的应用程序框架时,就已经为文档类提供了序列化的基本功能(即编程接口)。序列化是通过文档派生类的Serialize()函数来完成,该函数由CArchive类的ar对象指针作为参数,由一个if-else结构完成序列化的文档读写功能

21、。,Void CMydoc:Serialize(CArchive&ar)if(ar.IsStoring()/TODO:add storing code hereelse/TODO:add storing code here/*多数MFC程序实现对象的持久性是通过CArchive类(“归档类”)对象ar的安全缓冲机制间接地使用CFile类的功能,其中的关系如下:Serialize()ar对象 CFile对象 磁盘文件。*/当存储文档数据时,ar对象将序列化数据存放在一个缓冲区中,直到该区存满时才将数据存储到相关文件中;读取数据的过程与之相反。,实例:修改前述DrawCoins程序,使其具有文档序

22、列化功能void CDrawCoinsdoc:Serialize(CArchive*/,2、序列化实例总结当执行APP的文件菜单下的新建、打开、保存和另存为等命令时,都会自动调用文档派生类的Serialize()成员,实现与序列化有关的操作数据读写。例如,当执行“保存”命令时,MFC框架程序就会调用文档类的OnFileSave(),该函数完成如下3项工作:由文档对象获得当前文件CFile对象的指针,创建一个CArchive对象;文档对象调用Serialize()函数,并把CArchive对象对象作为参数;Serialize()函数根据IsStoring()函数的返回值true决定执行if语句的

23、第一个分支,从而利用ar对象将序列化数据存储至所关联的文件中。序列化的缺点:(1)只能顺序读写,不能随机读写;(2)只能处理二进制文件,不能处理文本文件。,九、滚动视图与多视图1、滚动视图本章前述的MFC框架程序的视图均派生于CView类,其用户区的大小总是固定的。如果某些程序的实际文档尺寸大于视图窗口时,超出的部分将无法显示,为了解决这种实际问题,就必须用到滚动视图,为视图加上滚动条,从而扩大显示的范围。MFC提供了一个滚动视图类(CScrollView),它有几种常用方法:SetScrollSizes()用于设置滚动视图的总尺寸以及每一页、每一行的大小;GetTotalSize()用于获取

24、整个视图的大小;GetScrollPosition()获取当前可见视图左上角的坐标。,将原有普通APP修改为具有滚动视图功能的程序的方法是:利用代码替换命令将所有视图的基类由CView改为CScrollView;重载视图类的OnInitialUpdate()虚函数或者OnCreate()函数,根据文档大小的需要重新设置滚动视图尺寸;一般为了简洁,可将滚动视图设成一个较大的常量值;在保存文档数据时,要进行相应的坐标数据转换,因为OnDraw()函数使用逻辑坐标,而鼠标控制的客户区使用的是设备坐标(由CClientDC界定)。,实例:为前述MyDraw程序增加滚动视图功能。(1)利用编辑菜单下的替

25、换命令将视图派生类.h和.cpp中的CView全部替换成CScrollView;(2)在工作区类视图中右键为视图类添加初始化虚函数,并在其中添加代码:CSize sizeTotal;sizeTotal.cx=sizeTotal.cy=1000;/定义新视图的尺寸SetScrollSizes(MM_TEXT,sizeTotal);/设置新视图的映射模式和大小(3)在保存滚动视图区新增画线的坐标数据时,应加上原始客户区的原点坐标;在鼠标移动消息函数中新增代码如下:CPoint ptOrg,ptStart,ptEnd;ptOrg=GetScrollPosition();/获得当前工作区原点坐标ptS

26、tart=m_pStart+ptOrg;/加上原点坐标用于修正线段坐标ptEnd=point+ptOrg;pDoc-AddLine(ptStart,ptEnd);/存储线段,2、多视图MFC的文档/视图结构可以使一个文档与多个视图相关联,容易实现多视图的APP。同一份文档数据即可以用文字方式显示,也可以用图形方式显示。MDI就是一种自然的多视图APP,但SDI程序也可以实现多视图。实例:以一个取名为MyEditor的MDI应用程序为例,实现文本字符串的两种视图显示方式。(代码详见MyEditor.txt文件)。,十、自定义类与类的序列化1、自定义类(新建类)在VC+编程中,多数的类都是由MFC

27、功能类直接派生的,在类向导的控制之下,管理起来比较方便。但有时,根据实际工作的不同,有些APP却需要程序员自己定义一个类,并由自己编写代码来实现类的功能。实例:现以前述MyDraw程序为例,由程序员自己创建一个CLine类,以方便数据管理,并实现程序结构的清晰化。实例MyDraw程序自定义类的实现过程详见“有彩色工具条的绘图程序”文本文件。,本例的关键技术还在于对MFC“动态数组”的运用,用它来保存不定数量的多条线段数据。(1)动态数组由类CObArray所支持的CObject指针数组对象动态生成;(2)代码实现时,实际上是引用了CTypedPtrArry类及其对象,典型格式是:CTypedP

28、trArryuseDefObj例如:CTypedPtrArray s_LineArray;本例中,useClass是Cline,useDefObj为m_LineArray,其表示m_LineArray是CObArray的派生类对象,用于存放Cline对象的指针。,2、自定义类的序列化在VC+编程中,只有由APP向导生成的程序框架的文档派生类才自动具有序列化功能,而由用户自定义的类必须人为通过书写代码,才可以使其支持序列化功能。自定义类支持序列化需满足4个条件:(1)自定义类必须直接或间接地从CObject类派生;(2)自定义类必须带有一个无参数的构造函数;(3)必须人为添加MFC序列化宏;(4

29、)必须重载Serialize()成员函数,使其支持特定数据的序列化;,实例:在MyDraw程序的基础上,通过对CLine类的序列化,使其具有画图的保存功能。分析:本实例先前所创建的Cline,是从CObject类派生,且已定义了一个不带参数的构造函数,符合序列化4个必须条件中的前两个。因此,本次编程要解决的是使其也满足后2个条件。(1)为新类添加必须的“序列化宏”DECLARE_SERIAL(CLine)/在类声明中加入“序列化宏”声明IMPLEMENT_SERIAL(CLine,CObject,1)/在实现文件中加入“实现宏”(2)在新类中手工重载序列化函数,并定义void CLine:Serialize(CArchive/读取对象的数据,(3)在原文档类的“序列化”函数中修改代码void CMyDrawDoc:Serialize(CArchive,课后作业,依照程序MyDraw编写一个名为MyLine的程序,类似windows的“画图”程序,在利用鼠标画一条直线时,按住左键拖拉,可以动态地画出当前直线,当释放左键后才真正画出一条所需要的直线。(要求实现窗口的重绘功能)提示:直线生成过程中,外形如同“橡皮筋”。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号