《毕业设计(论文)基于MFC的图象浏览器设计与实现.doc》由会员分享,可在线阅读,更多相关《毕业设计(论文)基于MFC的图象浏览器设计与实现.doc(25页珍藏版)》请在三一办公上搜索。
1、基于MFC的图象浏览器设计与实现摘 要:本论文介绍了基于VC+的图像浏览器的开发过程。该软件依据图形学的基本原理以及MFC类库开发而成,用于实现基本的图像浏览功能以及像的编辑、保存与修改等功能。程序开发过程中采用了面向对象技术,易于扩充和维护。它的设计与开发,为图形软件的研究提供了一个直观、便捷的集成环境,为今后图像系统的大规模开发提供了一个良好的平台。关键词: 图像; MFC; 文档; 浏览器Abstract: This paper introduced the VC + + based on the image browsers development process. The graph
2、ics software based on the basic principles and the MFC class library and was developed for the realization of the basic image browsing and as the editor, save and edit, and other functions. Procedures used in the process of developing object-oriented technology and easy expansion and maintenance. It
3、s design and development, graphics software for the study provides an intuitive and convenient integrated environment for future large-scale development of the imaging system provides a good platform. Key words: image; MFC; documents; browser目录第一章 绪论21.1文档视图结构21.2 DIB类的设计31.3同步缓冲和多线程并行处理51.4多线程MFC图像
4、处理程序的实现61.5程序测试实验8第二章 Visual C+ 的MFC 程序开发92.1DOS中C/C+应用程序的运行过程92.2MFC应用程序的运行过程102.3涉及的主要函数的作用11第三章 基于MFC的图像处理程序133.1MFC简介133.2软件界面及功能介绍143.3软件的基本数据结构143.4软件的实现163.5文件存储和读取17第四章 实现图像浏览器功能实现194.1工程的建立与基本界面的生成194.2视与视之间的通信22参考文献25第一章 绪论随着光电设备和计算机硬件的高速发展,数字图像处理技术在PC平台上的应用已经十分广泛通常情况下,这一类的分析处理过程往往需要使用专用软件
5、来完成,最为常见的有Matlab等。虽然这一类专用软件功能丰富、强大,但仍存在一定的局限性。以Matlab为例,该软件几乎具备了各种数据类型,甚至数据模型的分析处理能力;但也正是由于其功能过于丰富,并不能很好地满足各个方面的需求。另外,待处理的图像类型可能有很多种,如14位的红外传感器灰度图像,Matlab不可能保证兼容所有的类型。因此,单独开发专用的图像处理程序非常必要。MFC的出现使得程序快速开发成为可能,又由于其代码使用C+语言编写,运行效率高、执行速度快,非常适合图像处理方面的应用。1.1文档视图结构MFC支持三种类型的Windows应用程序:单文档(SDI)、多文档(MDI)和基于对
6、话框的应用程序。单文档程序每次只能维护一个文档1, 2,而多文档程序可以使用多个窗口,同时兼顾多个不同的文档,它们的不同仅仅在于多文档程序需要解决多个文档的数据管理方法的问题。注意,基于对话框的程序也可以维护自己的数据,只是由于其应用程序框架没有包含相应的成员函数,这些数据不能被当作“文档”来操作。简单地说,文档视图结构1, 2可以实现数据与数据的用户视图1的分离。一个明显的好处是,每一个文档可以有多个视图(但一个视图只能关联一个文档)。具体在图像处理程序中可以使用一个视图显示图像本身的同时,使用其他视图显示图像的直方图等信息。另外,文档视图结构中MFC提供了现成的绘图函数和打印函数,甚至文件
7、读写函数,这些都将大大方便图像处理程序的开发。文档视图结构的图像处理程序的运行步骤如图1所示。程序的运行大致分为初始化、文件载入、图像显示处理和结果保存几个步骤。程序的运行以Windows消息驱动模型3为基础,步骤间以Windows消息衔接,整个流程一气呵成。需要说明的是图1仅标出了几个重要的MFC消息(函数),它们是具体的编程过程中的主要工作部分。On New Document负责文档的初始化,视图的初始化应该在On Initial Update中完成,绘图在On Draw中完成,而On File Open和On File Save负责文档数据的加载和保存。图1MFC图像处理程序的执行流程1
8、.2 DIB类的设计图像处理程序的操作对象可以是各种各样的图像文件,但无论其格式如何,压缩方式如何,只要是Windows平台上显示输出,最终都必须转换成位图。这是因为Windows API和MFC中的GDI1, 3函数只能直接兼容位图操作。也就是说,程序载入图像数据后必须首先根据这些数据构造一个位图。又因为设备相关位图的局限性1,所以在图像处理程序中应该使用设备无关位图(DIB)来维护图像数据。 为了充分发挥C+语言的优势,并提高代码的复用性以及文档类的易操作性,程序应该引入一个DIB类。该DIB类用以表示和操作位图,将它嵌入到MFC的文档类中,可以大大地简化数据的操作。DIB类的设计应该考虑
9、以下因素:构造函数和析构函数、图像载入函数、图像存储函数以及必需的数据成员。下面的代码给出了一种合理的DIB类的设计方法。 Class CD ib: public C ObjectDECLARE_SERIAL(CDib)/声明为可串行化类public:LPVOID m_ lpv Color Table; /调色板指针LPBYTE m_lpImage;/图像数据块的指针LPBITMAPINFOHEADER m_ lpBMIH;/图像信息头的指针private:HGLOBALm_ hG lobal ;/图像数据块的句柄DWORD m_ d w Size Image; /图像数据块的大小intm_
10、n Color Table Entries; /调色板中的颜色数public: CDib ( ); /默认构造函数CDib (CSize size, int nB it Count);/一般构造函数,可以根据它构造位图信息头CDib ( ); /析构函数,用以释放位图对象和系统资源BOOL Draw(CDC* pDC, CRect dst);/用于在制定设备上的指定区域dst上显示位图BOOL Read(CFile* pFile); /从BMP文件读入BOOL Write (CFile* pFile); /写出到BMP文件void Serialize(CArchive& ar); /序列化位图
11、对象 以上的DIB类是一个简化设计,包含了DIB操作所必须的一些元素,没有涉及DIB和DDB间的转换,也没有使用GDI提供的与调色板相关的函数。调色板信息可以从BMP文件中获得,对于没有调色板信息但却需要调色板来显示的图像,也可以另外编程构造调色板。Read函数用于从BMP文件中直接读入位图,而对于其他格式的图像文件,则可以在读入像素数据块后用m_lpImage指向它即可。需要特别注意的一点是Draw函数中应该使用额外内存设备环境1来作为一级绘图缓存,这样做可以提高程序在指定设备上(CDC* pDC)的绘图效率,消除图像闪烁。1.3同步缓冲和多线程并行处理从第一节的分析可以看出,对于一帧的图像
12、的处理过程而言,可以分载入、显示处理和结果输出三个步骤。那么对于连续的、大量的图像序列而言,可以使用一种简单、常见的循环处理方法来实现。即利用一个单层的循环结构,以图像帧数N为循环条件,循环执行N次三个执行步骤即可。这种设计虽然实现简单,但却存在一个明显的缺陷在图像载入的过程中,浪费了宝贵的系统资源。因为图像加载过程其实就是从硬盘读入图像文件的过程,这一过程中对CPU及内存的使用都很少。这对于一两幅图像的处理可能没有多大的影响,但对于连续的大量图像文件处理来讲,将造成很大的浪费!而且,由于图像处理过程的运算量较大,单循环结构的程序只包含一个工作线程,它不能够很快地响应用户的输入。使用多线程同步
13、的多级缓存机制可以解决这一难题,如参考文献4中介绍的队列式的图像缓存技术。通过分析图像处理程序的工作原理,不难发现,系统资源的浪费主要是由于串行结构所造成的系统等待。那么使用一个专门的工作线程载入图像文件,另外一个线程进行图像的显示处理,两个线程并发,同时交替地访问两块内存单元,就可以解决这一问题。因此,同步缓冲只需要两块内存单元即可实现,无需队列式的多级缓存结构。使用TL代表工作线程Loader,它专门负责向内存单元内载入图像;TP代表工作线程Processor,它负责对图像进行处理,与Loader并行执行。系统的资源分配图5如图2所示。图2多线程处理结构中的资源调度黑色实线箭头的指向代表线
14、程请求的资源,而虚线的黑色箭头表示资源被分配给了它所指向的线程,每个执行周期完成后,两块内存位置交替。可以看出,系统的资源分配形成了一种环形的不安全结构5。因为,一旦某个线程的执行中止,它所掌握的资源不能得到释放,那么另外一个线程就会被“饿死”5,从而产生死锁5。因此,程序必须引入线程的同步机制。MFC提供了多种线程以及进程的同步机制,本文使用的是同步事件1, 3,在图2中用两个蓝色的箭头表示。两个线程分别并行操作两块内存单元,执行完成后进入循环等待状态,直到同步时间的触发,互斥解除为止。1.4多线程MFC图像处理程序的实现结合图2所给出的多线程同步缓冲的程序模型,首先在程序的初始化阶段应该创
15、建两个互斥事件,用于控制线程同步;另外使用Afx Begin Thread启动两个工作线程。因为线程相当于一个独立的程序,所以该操作可以在程序对象(CW in App)的初始化函数中完成,也可以在文档类的初始化函数On New Document或程序的其它类的初始化函数中完成。示例代码:hEventPaint=CreateEvent(NULL, FALSE, FALSE, NULL);/构造一个互斥事件,控制ThreadProcessorhEventLoad=Create Event(NULL, FALSE, FALSE,NULL);/构造一个互斥事件,控制ThreadLoaderpThrea
16、dLoader=AfxBeginThread(ThreadLoader, pDoc, THREAD_PRI-ORITY_ABOVE_NORMAL, 0,CREATE_SUSPENDED);/启动工作线程Loader,并将其挂起,进入准备状态pThread Processor=Afx Begin Thread (Thread Painter, p Doc, THREAD _PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);/启动工作线程Processor,并将其挂起,进入准备状态UINT Thread Loader(LPVOID lparam)C Docum
17、ent* p Doc = (C Docment* ) lparam;/文档指针作为参数被传递到线程函数while (TRUE) if(Wait For Single Object (hEventLoad, INFINITE) =WAIT_OBJECT_0 ) /在此处添加加载图像文件的代码Set Event (p Doc-h Event Paint); /图像加载完毕后触发互斥事件,启动Processor线程return 0;UINT Thread Processor(LPVOID lparam) C Document* p Doc = (C Document* ) lparam;POSITI
18、ON pos = p Doc-Get First View Position();C View* pView = (C View* )p Doc-Get Next View(pos); /通过传入的文档指针获得视图类指针Set Event(p Doc-h Event Load); /触发互斥事件,启动Loader的首次执行while (TRUE) if (Wait For Single Object(h Event Paint, INFINITE) =WAIT_OBJECT_0)P View-Invalidate(FALSE);/通知视图类进行图像刷新,Set Event(p Doc-h Ev
19、ent Load);/触发互斥事件,启动Loader的执行return 0;示例代码使用了Windows API函数3AfxBegin-Thread启动并挂起了线程,此时的工作线程处于挂起状态,没有得到执行也没有进入循环等待状态,之后必须使用CW in Thread. Resume Thread来使线程进入执行状态。又由于互斥事件的首次触发由Thread Processor完成,那么在线程的启动过程中必须注意要先启动Thread Processor然后才是Thread-Loader。对于线程的中止过程也是一样,必须先挂起Thread Processor,否则两个线程就会进入死锁状态。有关MFC
20、和Windows编程的更多细节请参见文献13。1.5程序测试实验程序实验的处理对象为分辨率为320240的14位灰度图像。处理过程包括直方图运算、时域平滑滤波和灰度拉伸运算(由14位灰度映射到Windows GDI所支持的8位灰度)。图3显示了分别使用串行循环处理结构和多线程并行处理结构的两个程序在处理过程中的CPU占用率。由于实验用PC使用双核心CPU,所以会有两个CPU使用记录的窗口。可以看出,使用多线程技术的图像处理程序充分利用了宝贵的CPU资源,而由于循环等待,一般结构的处理程序存在严重的串行循坏处理程序 多线并行处理程序图3两种程序结构的CPU占用率对比CPU资源浪费现象!在处理速度
21、的测试中,分别使用两个程序对3000帧连续图像进行处理。结果如表1。可以看出,通过节省CPU资源,多线程的并行处理程序的处理速度远大于一般结构程序。另外,在实际测试过程中,多线程程序的操作响应非常迅速,这也成为了它的优点之一。表1两程序的处理时间对比第二章 Visual C+ 的MFC 程序开发2.1DOS中C/C+应用程序的运行过程对于有DOS程序开发经验的编程者来说,都知道C/C+开发的DOS程序的人口函数是main()函数。C/C+编译器通过此函数加载程序。如以下程序:#include”stdio.hmain( )Int i;for(i=l00:i0:i-)Prinif(“%d”,i);
22、C/C+编译器先扫描源程序,发现main函数赋给相对地址,并在连接时确定绝对地址。以后,程序便从此地址开始执行。2.2MFC应用程序的运行过程同样,C/C+开发的Windows程序也有入口函数,就是Win Main( )函数(对于Visual C+而言)。然而MFC编程根本看不到Win Main ()函数,原因是Windows编程有很多工作是繁杂重复性工作,如窗口的设计、显示等,为了使开发人员从以前Windows编程那些烦琐的事情中解放出来,专心于程序设计与开发。Visual C+开发平台的ApWizard指定了Windows应用的许多特性,自动产生了一些类和资源及源代码。要查看Win Mai
23、n()函数,可使用Debug环境,在应用类的Initlnstance( )函数某处设置一个断点,然后执行出Initlnstance()函数就可见到Win Main()函数。如下例:# inelude”stdafx.h”# ifef-DEBUG#undefTHISFILEStatic charTHIS _ FILE =_FILE_:#endif/export Win Main to force linkage to this moduleExtern int AFXAPI Afx win Main (HINSTANCEhlnstanee,HINSTANCE hPrev lnstance,LPTS
24、TR lpCmdLine,int nCmdshow);#ifef_MACExtern “C”一ntPASCAL#elseexterl、“C”intWINAPI#erldlf_twin Main (HINSTANCE hlnstance.HINSTANCEhPrevlnstance.LPTSTR IpCmd Lineint nCmd showcall、shared/exported win Mainreturn Afx Win Main (hlnstance,hPrevlnstarlee,lpCmdline,nCmd Show); 用MFC开发的应用程序执行过程为:运行应用时,Windows会自
25、动调用应用框架内部的Win Main ( )函数,Win Main ( )函数会去查找该应用的全程构造对象,然后调用其中的InitInstance( )成员函数,该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。工作流程如图1所示。2.3涉及的主要函数的作用(1)Initlnsranee()函数1)创建文档模板,并由文档模板来创建文视图、框窗;2)对当前应用程序实例进行初始化;3)决定窗口的风格,对话框的背景色;4)决定MRU及命令行格式。(2)Run()函数l)执行消息循环;2)接受各种消息;3)分配消息至相应的响应函数。(3)Onldle()函数在无消息时进行空操作以等待下一个消息
26、到来(4)Existlnstanee()函数1)撤消申请的内存空间;2)对文件进行存储等操作;3)进行退出应用的收尾工作。由此可见,MFC程序员的主要任务是决定哪个消息映射到哪个对象上,然后实现这一映射,即编写消息映射函数。第三章 基于MFC的图像处理程序3.1MFC简介MFC是用来编写Windows应用程序的C+类集该类集是按层次结构组织起来的,其中封装了大部分Windows API函数和Windows控件,它所包含的功能涉及到整个Windows操作系统。MFC不仅为用户提供了Windows图形环境下应用程序的框架,而且还提供了创建应用程序的组件。使用MFC类库和Visual C+提供的高度
27、可视的应用程序开发工具,可使应用程序开发变得更简单,极大地缩短开发周期,提高代码的可靠性和可重用性2。 MFC库中的类按层次关系可分为如下若干类:*根类:Cobject;*应用程序体系结构类;*窗口、对话框和控件类;*绘图和打印类;*简单数据类型类;*数组、列表和映像类;*文件和数据库类;* Internet和网络工作类;* OLE类;*调试和异常类。 其中,和图形软件密切相关的类是根类、应用程序体系结构类、窗口、对话框和控件类、绘图和打印类、文件和数据库类。3.2软件界面及功能介绍该软件的功能设计主要依据计算机图形学的基本绘图原理设计而成,其设计风格参照了AutoCAD的界面风格。应用程序界
28、面如图1所示。图3-1应用程序窗口应用程序窗口中包括标题栏、菜单栏、工具栏、绘图区和状态栏。所完成的主要功能包括:(1)基本图元的绘制,如直线、折线、圆、椭圆、圆弧、球、长方体等。(2)线型及色彩的控制。(3)图形变换,包括图形的拾取、平移、旋转、镜像、填充等。(4)图形文件的保存及读取功能。以上所述功能已构建了一般图形应用软件的基本框架,新的绘图及图形变换功能只需在此基础上加以扩充即可。由于本系统采用面向对象技术,是一个开放式系统,所以使得它的扩充易于进行。这为图形系统的后续开发奠定了良好的基础。3.3软件的基本数据结构本软件充分利用了面向对象的设计思想,按照功能来设计类的层次结构3。程序中
29、共有两个基类,一个是图形类,一个是命令类。(1)在图形类中,封装了绘制一个图元所需的基本数据结构。如图2所示是图形类及其子类的层次结构,限于篇幅,图中并未画出所有的派生类,各子类的关系是并列的。图2图形类及其派生类 * CEntity:图形基类,封装了图元的基本特征。下面是其数据结构的主要部分。class Centity: public C Objectprotected:int m-type; /图元类型UINT m-line Style; /图元线型COLORREF m-color; /图元颜色int m-line Width; /图元线宽COLORREF m-brush; /图元画刷;*
30、 CLine:直线类,由图形基类派生,封装了直线特征class CLine: public CEntityprotected:Point m-begin, m-end; /图元的起点和终点;* CRectangle:矩形类,由图形基类派生,封装了矩形特征。* CCirle:圆类,由图形基类派生,封装了圆特征。* CArc:圆弧类,由图形基类派生,封装了圆弧特征。* CPoly Line:折线类,由图形基类派生,封装了折线特征。* CSphere:球类,由图形基类派生,封装了球特征。*其他:包括各图元的填充类,均由图形基类派生。(2)命令类则是依据上述数据结构创建一个图元。如图3所示是命令类及其
31、子类的层次结构,同样,图中也未画出其所有子类。图3命令类及其派生类* CCommand:命令基类。* CCreat eLine:创建直线类,由命令基类派生,封装创建直线操作。* CCreate Rectangle:创建矩形类,由命令基类派生,封装创建矩形操作。* CCreate Cirle:创建圆类,由命令基类派生,封装创建圆操作。* CCreate Arc:创建圆弧类,由命令基类派生,封装创建圆弧操作。* CMirror:封装镜像操作,由命令基类派生。* CMove:封装移动操作,由命令基类派生。* CRotate:封装旋转操作,由命令基类派生。*其他:包括封装属性、封装局部显示操作、擦除操
32、作等等,均由命令基类派生。3.4软件的实现以下是软件的实现过程4。(1)首先利用VC+的应用程序向导生成应用程序的框架,设置为单文档应用程序即可。(2)向应用程序添加所需的资源,如菜单、对话框、按钮、滚动条、工具条等。(3)为相应的资源添加命令和响应消息。当发生某个消息(比如用户移动了鼠标和按下了键盘)时,该消息进入消息队列,操作系统根据消息提供的信息决定由哪个应用程序来处理,该应用程序依照一定的方式查找应用程序中各个类的消息映射(一组宏,这些宏用来确定某个消息及相应的处理程序的对应关系),找到处理程序,然后由处理程序执行。例如在此程序中,绘制直线的消息处理过程为:a.通过菜单或工具条进入绘制
33、直线命令状态;b.当客户单击鼠标左键,系统将消息WM-LBUT-TONDOWN传送给视图对象,视图对象接受消息,然后视图对象通过手工触发的方法,将消息传递给绘制直线类命令,绘制直线类对象接受到消息,根据自身的特点和当前CCreate Line:OnL Button Down中的代码,将消息处理的结果反馈给消息对象或文档对象。(4)定义全局变量并设置软件的环境。在该软件中,很多函数在实现中都会和文档或视图发生关系,如在绘制直线时,需要将直线保存在文档图形元素的链表中,而为了在屏幕上显示就要从视图类得到设备环境指针,为了方便地调用文档或视图,笔者将文档和视图指针设置为全局变量。在头文件GraDes
34、.h中,定义文档和视图指针如下:CGraDes View *g-pView; /全局变量,视图类指针CGraDes Doc *g-pDoc; /全局变量,文档类指针在文档类中定义图形元素的链表,它将图形数据保存在内存中,可以动态地对图形进行修改。CObList m-EntityList; /链表,保存图元对象指针CObList m-EntityList; /恋表,保存图元对象指针CObArray m-SelectArray; /数组,保存被选中的图元指针(5)为类的各成员函数编写代码,从而最终完成对图形的各种操作。3.5文件存储和读取存储就是将图形文件所绘制的各种图元以二进制文件形式存储到硬盘
35、上,永久保存。读取就是将硬盘存在的图形文件(系统可识别)读到内存中,再由图形系统显示到屏幕上。MFC通过调用SeriaLize函数来实现串行化输入输入操作,从而实现文件的存储和读取。 / GraDesDoc.hvoid GraDesDoc:SeriaLize(CArchive&ar)m-EntityList.Se-riaList(ar);参数ar是一个CArchive类的对象,可对CObject类的派生类的实例进行序列化操作。这里采用图元对象链表CObList类对象m-EntityList支持串行化操作,方便存取。在这里,采用了矢量方法来保存图形,而不是通常的位图方式。整个图形是保存在一个链表
36、中的,图形是由一系列图元组成的,因而链表中存放的是一系列指向各图元的指针,再由各个指针指向各图形对象,如图4所示。图4图形链表需要说明的是,由于CLine类是CEntity的子类,而CEntity又是CObject的子类,所以CObject类的虚基类指针可以访问它的派生类对象。第四章 实现图像浏览器功能实现图像的显示和浏览功能是图像处理软件的基本功能,PHOTOSHOP等优秀的图像处理软件一般都提供图像浏览器(也称“鹰眼,)的功能,旨在方便用户在放大显示局部图像的同时又能了解到局部图像在整幅影像中位置。笔者用VC+ +6.0为正在制作的正射影象生成工作站成功地添加了图像浏览器功能,大大方便了图
37、像的显示、放大和漫游。(程序的运行界面见图一)以下通过两部分介绍制作的主要过程和原理。其中第一部分主要介绍工程的建立和基本界面的生成,第二部分介绍视与视之间的通信。4.1工程的建立与基本界面的生成1.启动VC+ +6.0,点击菜单File一New一Project,选MFC AppWizard(exe)建立一个新工程OS21,在Step 1中选Single Document,从Step 2到Step 6都按缺省设置即可,点击Finish生成相应的源代码。为了叙述方便表1将叙述所用到的类进行了归纳。表1在CContralView中定义四个Public型的公用数据变量,分别为实际的影像显示比例Zoo
38、mPercent ( float型),最小和最大缩放倍数MinZoom, ZoomMax (float型),以及在浏览框中代表图像位置的红色矩形框(见图一示)RedRect (CRect型)。这里显示比例ZoomPercent定义为实际屏幕显示宽度和区域影像原始宽度的比值乘100,例如:一块原始宽度为1024的图像,当屏幕上显示宽度为512时其ZoomPercent二512/ 1024 * 100 =SO.OOo MinZoom和ZoomMax则为ZoomPercent所允许取得的最小值与最大值,视需要而定。以上四个变量是实现CCon-tralView对COS21View控制的桥梁。2.在资源
39、编辑器内为浏览器制作一个对话框资源IDC ContralView,因为我们要制作的浏览器基类选择CFor-mView类,所以在设置对话框属性时要注意以下三项设置:Style=ChildBorder=NoneVisible=unchecked接着在C1assWizard中为制作的对话框资源生成相应的类CContralView,当然此时的基类应选为CFormView,并在COS21 App: : InitInstance)中增加以下文档模板CSingIeDocTemplate*pDocTemplatel;pDocTemplatel二new CSingIeDocTemplate( 旧R一ontrol
40、Type RUNTIME一LASS ( COS21 Doc 1 RUNTIME一LASS ( CMainFrame 1/main SDI frame window RUNTIME一LASS(CContralView);AddDocTemplate (pDocTemplatel)图13.为了创建如(图1)所示的分离栏在CMainFrame类中增加OnCreateClient函数及以下代码BOOLCMainFrame:OnCreateClient(LPCREATESTRUCT IpcsCCreateContext*pContext )VERIFY(m wndSplitter. CreateStat
41、ic(this, 1, 2);m wndSplitter. CreateView(0, 0, RUNTIME一LASS ( CContral-View ),CSize(0, 0),pContext );m wndSplitter. CreateView(0, 1, RUNTIME一LASS(COS21-View ),CSize(0, 0), pContext);CContralView*pWnd=(CContralView*)m wndSplitter.GetPane ( 0, 0 );CSize size=pWnd一 GetTotaISize();m wndSplitter. SetColu
42、mnlnfo(0, size. cx, 0);return TRUE; m wndSplitter定义为CSplitterWnd的一个派生类CLock-Splitter的实例,有关分离栏创建的资料很多,不再赘述.4.2视与视之间的通信图2介绍了两个视在用户点按放大、缩小按钮,拉动滑动图2杆时以及点选浏览窗口的不同部分时CContralView和COS21 View互通信息以实现图像的放大、缩小及漫游的主要原理。如图所示当上述事件发生时,CContralView类会重新计算RedRect的大小和位里,并通过RedRect将影像显示的区域传给COS21View,然后通知COS21 View类进行刷
43、新,自定义函数CContralView: MoveImage()体现了这一过程。在刷新过程中COS21View又会将计算出的最小和最大缩放倍数MinZoom,而仲此公及实际的显示比例ZoomPercent提供给CContralView使用。BOOL CContralView:Movelmage)if ( FileOpen=TRUE)CRect rect CheckZoom(); RedRect=CaIRect ( MousePos );/计算RedRect OIdRect二CaIRect ( OIdPoint ); UpdateFrame);/擦除旧矩形 COS21 View*pView =
44、pDoc一pOS21 View;/获取主窗口视指针 pView-GetCIientRect(& recd; pView一InvalidateRect(rect, FALSE);pView一UpdateWindow();/主窗Ca刷新return TRUE 除了明确原理以外,实现时还应注意以下细节。 1.获取两个视的指针。在两个视的通信过程中,必须获得彼此的指针,因此需在文档类COS21 Doc中设置两个公用指针型数据变量pContralView和pOS2lView,并在经重载后的COS21 Doc:OnOpenDocument)函数中加入以下语句使得在文档打开后能获取正确的地址值。 POSlT
45、旧N pos二GetFirstViewPosition();/获取首个与文档相连接的视的位置 CView*pFirstView; while (pos!=NULL) pFirstView=GetNextView ( pos );/获取首个与文档相连接的视的指针 2.在打开一个文档正式显示之前,需要初始化RedRect和MinZoom,ZoomMax。由于两个视之间通信的复杂性,这些工作的顺序显得尤为重要。在给出经重载后的COS21Doc:OnOpenDocument)的源代码的基础上,图3对初始化的内容和顺序作了说明。图3简而言之,由于在COS21 View中显示图像必须用到Ccon-tralView中的RedRect,所以将CContralView的一部分初始化工作及图像显示最先进行,接着在COS21 View中显示图像并计算MinZoom等值,最后利用这些值在CContralView的自定义函数FileOpenWork)完成对CContralView中的按钮、滑动条控件的设置。另外应说明的是在CcontralView和COS21 View中都定义了一个BOOL型变量FileOpen,这是为了在进行显示刷新等操作时与空白文档有所区别。 3.介绍在CContralView中完成一部分初始化工作的