VC第三章,MFC框架之文档与视图_第1页
VC第三章,MFC框架之文档与视图_第2页
VC第三章,MFC框架之文档与视图_第3页
VC第三章,MFC框架之文档与视图_第4页
VC第三章,MFC框架之文档与视图_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

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

文档简介

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

2、件将项目详细情况组合到其中dsp项目文件存储项目的详细说明hc+头文件存储类及其成员的声明代码cppc+源文件存储类成员函数的实现代码rc资源脚本文件存储菜单、工具栏、对话框资源rc2资源文件用于将资源包含到项目中ico图标文件存储应用程序图标bmp位图文件存储各种位图clw类向导文件存储类向导使用的类信息ncb没有编译的浏览文件保留类视图和类向导使用的详细情况opt可选项文件存储自定义的工作区的显示情况 mfc中资源标识符前缀标识符前缀说 明idr_主菜单、工具栏、图标和快捷键表资源idd_对话框资源idc_各种控件和光标ids_字符串资源idp_信息对话框的字符串id_菜单命令项三、cla

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

4、右单击操作添加“消息处理函数”onlbuttondown()和onrbuttondown();为onlbuttondown()函数添加功能代码,右键函数与此类似m_nleft+;cstring stroutput;stroutput.format(“鼠标左键单击的次数为:%d”, m_nleft);messagebox (stroutput);编译、链接并运行程序,测试程序效果。3、文档、文档/视图的相互作用函数视图的相互作用函数(1)视图类的)视图类的getdocument()函数函数(2)文档类的)文档类的updateallviews()函数函数(3)视图类的)视图类的onupdate()

5、函数函数支持文档支持文档/视图相互作用的函数还有:视图相互作用的函数还有:oninitialupdate()onnewdocument() 实际上,刷新视图的一般过程是:实际上,刷新视图的一般过程是:cdocument:updateallviews() cview:onupdate() cview:invalidate() onpaint() ondraw()4、多文档、多文档mfc多文档应用程序与单文档程序的根本差别多文档应用程序与单文档程序的根本差别mdi窗口类的派生关系如下:窗口类的派生关系如下:cmdiframewnd:cmainframe主框架窗口类主框架窗口类;cmdichildw

6、nd:cchildframe子框架窗口类子框架窗口类;文档模板文档模板描述了对应于每一种类型文档的视图和窗口的类型,由其描述了对应于每一种类型文档的视图和窗口的类型,由其来确立文档、视图、框架和各种资源之间的固定关系。来确立文档、视图、框架和各种资源之间的固定关系。sdi和和mdi文档模板的样式:文档模板的样式:文档模板是在文档模板是在app类的初始化函数类的初始化函数initinstance()中声明。中声明。csingledoctemplate* pdoctemplate;pdoctemplate = new csingledoctemplate( /单文档模板单文档模板idr_mainf

7、rame, /主框架资源的主框架资源的idruntime_class(cmysdidoc), /sdi文档类文档类runtime_class(cmainframe), / sdi主框架窗口类主框架窗口类runtime_class(cmysdiview); /sdi视图类视图类adddoctemplate(pdoctemplate);/cmultidoctemplate* pdoctemplate;pdoctemplate = new cmultidoctemplate(idr_mymditype,/子框架窗口资源子框架窗口资源idruntime_class(cmymdidoc),runtime

8、_class(cchildframe), / mdi子框架窗口类子框架窗口类runtime_class(cmymdiview);adddoctemplate(pdoctemplate);五、菜单设计及应用五、菜单设计及应用1、建立菜单资源、建立菜单资源实例:创建一个名为drawcoin的sdi项目,添加“画硬币”主菜单,并增加两个菜单项“增加硬币”、 “减少硬币”。编程:(1)添加顶层菜单“画硬币(&c)”(2)增加两个菜单项(menu item)id_coin_add 增加硬币(&a)tctrl+a 在客户区增加一枚硬币n增币id_coin_sub 减少硬币(&s)t

9、ctrl+s 在客户区减少一枚硬币n减币2、添加菜单命令的处理函数、添加菜单命令的处理函数菜单实则一系列命令的列表,当某一菜单项被点击后,一个含有该菜单项id标识的wm_command命令消息将发送给app窗口,app将该消息转换为一个“命令消息处理函数”的函数调用,从而响应命令。利用“类向导”(ctrl+w)工具为菜单添加消息映射函数,并添加用户代码:在oncoinadd()函数中添加在oncoinsub()函数中添加m_ncoins+; /硬币加一updateallviews(null); /刷新视图if(m_ncoins0)m_ncoins-; /硬币减一updateallviews(n

10、ull); /刷新视图本例中,为了实现菜单的操作功能,还必须完成如下三步:(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);pdc-ellipse(200,y-10,300,y-35); /用

11、两个上下偏移椭圆表示硬币update_command_ui是“更新用户界面命令消息”:它能够根据程序当前运行状态来动态设置菜单项的状态(可用或不可用)。在程序刚运行时,将菜单项“减少硬币” 置为“不可用”(灰显状态)。需要在其update_command_ui消息映射函数中,添加代码:if (m_ncoinsenable(false);/禁用菜单项(灰显)elsepcmdui-enable(true);/使能菜单项(正常显示)3、为菜单命令设置加速键、为菜单命令设置加速键在资源视图accelerator中idr_mainframe项的加速键列表最后一空行操作。4、为新菜单添加、为新菜单添加“弹

12、出式快捷菜单弹出式快捷菜单”利用类向导为视图类添加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(tpm_le

13、ftalign,point.x,point.y,this);六、鼠标消息的处理六、鼠标消息的处理1、鼠标消息的类型、鼠标消息的类型wm_mousemove(移动); wm_lbuttondblclk(双击左键);wm_lbuttondown(按下左键);wm_lbuttonup(释放左键);wm_rbuttondown(按下右键);wm_rbuttonup(释放右键);(1)客户区鼠标消息(最常见)(2)非客户区鼠标消息(相对少见)2、鼠标消息的应用举例、鼠标消息的应用举例实例:编写一个sdi程序mydraw,程序运行后,当用户在客户区内按下鼠标左键并移动时,会沿鼠标移动轨迹自动绘制出连续的线

14、段。分析:本例属典型的“客户区鼠标消息”的应用。编程实现:(具体步骤及代码详见mydraw.txt文件)七、工具栏与状态栏设计七、工具栏与状态栏设计1、添加工具栏按钮的方法、添加工具栏按钮的方法工具栏是由形象化的位图按钮所组成,它结合了菜单和快捷键的共同优点,具有操作直观快捷,使用方便的特点。工具栏内的按钮一般都与某一特定的菜单命令相对应,从功能上讲,它与特定菜单命令一致。在具体编程实现上,程序员应当先利用资源视图设计出新按钮图形图标,后将其id值设置成与对应菜单项id相同即可。实例:为前述的drawcoins程序的工具栏添加两个对应按钮.2、添加用户自定义工具栏的方法、添加用户自定义工具栏的

15、方法添加用户自定义工具栏步骤:(1)在工程中插入新工具条资源, 并添加相关按钮;(2)在cmainframe类头文件中加入:ctoolbar my_toolbar;(3)在mainframe.cpp文件的create()函数中模仿生成标准工具栏的方法, 书写生成新工具栏的语句, 并在最后“停泊工具栏”的函数中加入第2个参数afx_idw_dockbar_left;(4)为工具条的各个按钮添加update_command_ui和command类型的消息映射,并添加实现代码;(5)在”查看”菜单中为新工具条的添加控制菜单命令;在消息映射处理函数中以 iswindowvisible()函数为判断条件

16、,以showwindow()函数的sw_hide或sw_show参数控制,以决定其显隐。实例:为实例:为mydraw画线程序添加画线程序添加“画笔选择画笔选择”工具栏(该例以另一种方式实现工工具栏(该例以另一种方式实现工具栏按钮的基本功能)具栏按钮的基本功能).(1)在视图类中头文件中手工添加工具条的消息映射函数的声明:afx_msg void onpenchioce(uint nid);(2)在实现文件中加入消息映射宏:on_command_range(id_pen_red,id_pen_width,onpenchioce)(3)在实现文件中加入消息处理函数的定义:void cmydrawv

17、iew:onpenchioce(uint nid)switch(nid)/以下case语句分别对应于画笔工具条自左向右的各个按钮控件case id_pen_red:m_colors=rgb(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); /

18、创建画笔(4)为工具条的某些按钮继续书写函数功能定义代码,如penwidthdlg()3、定制状态栏、定制状态栏状态栏是位于主窗口底部,用于显示当前操作提示信息和键盘状态的长条型子窗口,一般由状态信息行和状态指示器两部分组成。前者用于动态地显示app串表资源中的字符串,后者用于显示键盘的状态信息。通常,mfc程序将状态条自左向右分成4个窗格:(1)窗格显示菜单或工具栏的提示信息;(2)窗格显示键盘的大小写状态; (3)窗格显示数字键盘状态; (4)窗格显示键盘的scroll lock状态。在mainframe.cpp文件中,statusbar由一个静态数组来定义:static uint ind

19、icators =id_separator, /定义分隔符,作为提示信息行的面板标识id_indicator_caps,/大小写指示器面板标识id_indicator_num,/数字指示器面板标识id_indicator_scrl,/滚动指示器面板标识;cstatusbar类有两个重要函数:setpanetext()用于在指定窗格上显示字符信息,setpaneinfo()可改变一个指示器面板的id、风格和宽度。实例:修改前述drawcoins程序的状态栏,使其能动态显示硬币数目。(1)在 “string table” 中加入新的字符串信息,其id为id_indicator_coins,capt

20、ion为”硬币数目”。(2)在mainframe.cpp中修改indicators 数组:static uint indicators =id_separator, /定义分隔符,作为提示信息行的面板标识id_indicator_coins,/新添加一个指示器面板标识id_indicator_caps,/大小写指示器面板标识id_indicator_num,/数字指示器面板标识id_indicator_scrl,/滚动指示器面板标识;(3)在视图类的ondraw()函数中定制状态栏新窗格的显示信息在在ondraw()函数中添加如下代码:函数中添加如下代码:cstring strcoins;/声

21、明状态栏新窗格的字符串变量cstatusbar * pstatus=(cstatusbar * )afxgetapp()-m_pmainwnd-getdescendantwindow(id_view_status_bar); /状态栏指针if(pstatus)strcoins.format(当前硬币个数:%d, pdoc-m_ncoins);pstatus-setpaneinfo(1,1,null,98);/指定序号窗格的宽度pstatus-setpanetext(1,strcoins);/在指定窗格显示硬币个数编译并运行,检验正误。编译并运行,检验正误。八、文档的读写在mfc中,cfile类

22、专门用于处理文件,使用它,需要在程序中包含afx.h的头文件,而且还需要对工程进行特定设置,即project | settingslink标签页mfc项use mfc in a dll or static library。使用该类的缺点在于打开或读写文件时可能发生异常情况,需要进行复杂的异常处理。对于二进制文件来说,mfc使用“序列化”简化了文件的读写操作。1、序列化(、序列化(serialize)持久性是指对象所具有的保存和加载其状态的能力,在程序运行结束之前通过将对象的当前状态写入永久性存储体中,在下次再运行时通过数据的读取而恢复对象的状态。在mfc所支持的app框架程序中,对象的保存和恢

23、复的过程就称为“序列化”。在利用app向导生成文档/视图结构的应用程序框架时,就已经为文档类提供了序列化的基本功能(即编程接口)。序列化是通过文档派生类的serialize()函数来完成,该函数由carchive类的ar对象指针作为参数,由一个if-else结构完成序列化的文档读写功能。void cmydoc:serialize (carchive &ar)if(ar.isstoring()/todo:add storing code hereelse/todo:add storing code here/* 多数mfc程序实现对象的持久性是通过carchive类(“归档类”)对象ar

24、的安全缓冲机制间接地使用cfile类的功能,其中的关系如下: serialize()ar对象 cfile对象 磁盘文件。*/当存储文档数据时,ar对象将序列化数据存放在一个缓冲区中,直到该区存满时才将数据存储到相关文件中;读取数据的过程与之相反。实例:修改前述drawcoins程序,使其具有文档序列化功能void cdrawcoinsdoc:serialize (carchive &ar)if(ar.isstoring()/todo:add storing code herearm_ncoins;/读取硬币数量/数据出栈/提取符/*在视图类ondraw()函数中设置文档修改标志:pdo

25、c-setmodifiedflag(); */2、序列化实例总结、序列化实例总结当执行app的文件菜单下的新建、打开、保存和另存为等命令时,都会自动调用文档派生类的serialize()成员,实现与序列化有关的操作数据读写。例如,当执行“保存”命令时,mfc框架程序就会调用文档类的onfilesave(),该函数完成如下3项工作:a)由文档对象获得当前文件cfile对象的指针,创建一个carchive对象;b)文档对象调用serialize()函数,并把carchive对象对象作为参数;c)serialize()函数根据isstoring()函数的返回值true决定执行if语句的第一个分支,从

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

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

28、生类.h和.cpp中的cview全部替换成cscrollview;(2)在工作区类视图中右键为视图类添加初始化虚函数,并在其中添加代码:csize sizetotal;sizetotal.cx=sizetotal.cy=1000;/定义新视图的尺寸setscrollsizes(mm_text,sizetotal);/设置新视图的映射模式和大小(3)在保存滚动视图区新增画线的坐标数据时,应加上原始客户区的原点坐标;在鼠标移动消息函数中新增代码如下:cpoint ptorg, ptstart, ptend;ptorg=getscrollposition(); /获得当前工作区原点坐标ptstart

29、=m_pstart+ptorg; /加上原点坐标用于修正线段坐标ptend=point+ptorg; pdoc-addline(ptstart, ptend);/存储线段2、多视图mfc的文档/视图结构可以使一个文档与多个视图相关联,容易实现多视图的app。同一份文档数据即可以用文字方式显示,也可以用图形方式显示。mdi就是一种自然的多视图app,但sdi程序也可以实现多视图。实例:以一个取名为myeditor的mdi应用程序为例,实现文本字符串的两种视图显示方式。(代码详见myeditor.txt文件)。十、自定义类与类的序列化1、自定义类(新建类)、自定义类(新建类)在vc+编程中,多数的

30、类都是由mfc功能类直接派生的,在类向导的控制之下,管理起来比较方便。但有时,根据实际工作的不同,有些app却需要程序员自己定义一个类,并由自己编写代码来实现类的功能。实例:现以前述mydraw程序为例,由程序员自己创建一个cline类,以方便数据管理,并实现程序结构的清晰化。实例mydraw程序自定义类的实现过程详见“有彩色工具条的绘图程序”文本文件。本例的关键技术还在于对mfc“动态数组”的运用,用它来保存不定数量的多条线段数据。(1)动态数组由类cobarray所支持的cobject指针数组对象动态生成;(2)代码实现时,实际上是引用了ctypedptrarry类及其对象,典型格式是:ctypedptrarryusedefobj例如:ctypedptrarray s_linearray;本例中,useclass是cline, usedefobj为m_linearray,其表示m_linearray是cobarray的派生类对象,用于存放cline对象的指针。2、自定义类的序列化、自定义类的序列化在vc+编程中,只有由app向导生成的程序框架的文档派生类才自动具有序列化功能,而由用户自定义的

温馨提示

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

评论

0/150

提交评论