




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
用c开发电子电路制图软件【摘要】mfc借助c+的优势为windows开发开辟了一片新天地,同时也借助applicationwizzard使开发者摆脱离了那些每次都必写基本代码,借助classwizard和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。更令人兴奋的是利用c+的封装功能使开发者摆脱windows中各种句柄的困扰,只需要面对c+中的对象,这样一来使开发更接近开发语言而远离系统。正因为mfc是建立在c+的基础上,利用c+的封装性开发者可以更容易理解和操作各种窗口对象;利用c+的派生性开发者可以减少开发自定义窗口的时间和创造出可重用的代码;利用虚拟性可以在必要时更好的控制窗口的活动。而且c+本身所具备的超越c语言的特性都可以使开发者编写出更易用,更灵活的代码。本论文就是用c+语言开发了一个功能简易的电子电路制图软件,主要用于电子电路工程人员通过计算机交互设计与修改电路原理图。解决工程人员手工绘图各种不足的问题。它的主要功能如下:1. 绘图区域操作(新建、打开、保存、关闭、打印、打印预览、打印设置)2. 用工具栏中绘图工具绘电子元件(电阻、电容、电感、开关、二极管、三极管、 )3. 元件编辑(参数属性、位置调整、缩放、删除、移动、剪裁、拷贝、粘贴、颜色修改、大小、线条粗细)4、鼠标联线5联线编辑(颜色修改、大小、线条粗细、删除)。【关键词】 计算机制图软件,图形编程技术,cad,gdi,mfc目录前言31.电子线路计算机辅助设计应用31.1电子线路计算机辅助设计发展与应用31.2电子线路基本过程32.系统开发32.1c+的诞生32.2windows 图形编程基本技术42.2.1图形设备接口()42.2.2设备环境42.3mfc 中与图形相关的类介绍42.3.1cdc类52.3.2gdi对象类62.3.3cdc类和gdi对象类合作62.3.4坐标变换和映射模式72.3.5onpaint()和ondraw()72.4序列化72.4.1序列化概念82.4.2序列化机制82.4.3实现类的序列化82.4.4文档、视图架构程序中数据的序列化82.5电子线路绘制系统的需求分析。92.5.1绘制功能92.5.2图形编辑功能92.5.3器件属性的编辑92.5.4保存器件图,电路图102.6重点功能实现方法(具体代码见附件)102.6.1绘制器件图102.6.2选择器件图112.6.3器件图的放大、缩小、单个器件图的移动132.6.4器件图的_order顺序调整142.6.5复制、粘贴142.6.6载获windows的消息实现多个器件图的移动152.6.7实现器件之间的连接线153.结束语20致谢21参考文献21附件:22前言 语言的发展是一个逐步地进的过程,c+是直接从c语言发展过来的,而c语言是从b语言发展过来的,b语言是bcpl的一个解释性后代,bcpl是basic cpl。其中最有趣的是cpl中c的由来,由于当时这个语言是剑桥大学和伦敦大学合作开发的,在伦敦的人员加入之前,c表示剑桥,伦敦人员加入之后,c表示combined组合。还有一种非正式的说法,c表示christopher,因为christopher是cpl背后的主要动力。 最初导致c+诞生的原因是在bjarne博士等人试图去分析unix的内核的时候,这项工作开始于1979年4月,当时由于没有合适的工具能够有效的分析由于内核分布而造成的网络流量,以及怎样将内核模块化。同年10月,bjarne博士完成了一个可以运行的预处理程序,称之为cpre,它为c加上了类似simula的类机制。在这个过程中,bjarne博士开始思考是不是要开发一种新的语言,当时贝尔实验室对这个想法很感兴趣,就让bjarne博士等人组成一个开发小组,专门进行研究。 当时不是叫做c+,而是c with class,这是把它当作一种c语言的有效扩充。由于当时c语言在编程界居于老大的地位,要想发展一种新的语言,最强大的竞争对手就是c语言,所以当时有两个问题最受关注:c+要在运行时间、代码紧凑性和数据紧凑性方面能够与c语言相媲美,但是还要尽量避免在语言应用领域的限制。在这种情况下,一个很自然的想法就是让c+从c语言继承过来,但是我们的bjarne博士更具有先见之明,他为了避免受到c语言的局限性,参考了很多的语言,例如:从simula继承了类的概念,从algol68继承了运算符重载、引用以及在任何地方声明变量的能力,从bcpl获得了/注释,从ada得到了模板、名字空间,从ada、clu和ml取来了异常。vc+应用程序的开发主要有两种模式,一种是win api方式,另一种则是mfc方式,传统的win api开发方式比较繁琐,而mfc则是对win api再次封装,所以mfc相对于win api开发更具备效率优势,随着技术和经济的发展整或是电子工程研发人员因设计失误等常要对一些电子电路原理图进行多次修改或增减电路,这就需要修改或重新制作图纸。传统的电路原理图纸方法制作不灵活,修改不方便。另外网络图纸制作的显著特点是线段、同一形状的图形用得较多。因此电子线路制图软件在这方面具有绝对优势,能方便地对原图纸进行修改,编辑好的图形能重复调用。电子线路制图软件,广大电子工作者对其并不陌生,可用它来制作电子线路电原理图、pcb板图。这类软件常见的有protel、pads2000、caxa、orcad、winroute等。电子电路绘制系统的主要目的是帮助电子工程人员利用计算机完成电路板上常见元器件的绘制。1. 电子线路计算机辅助设计应用1.1电子线路计算机辅助设计发展与应用电子线路计算机辅助设计()是六十年代以来迅速发展起来的一门新技术、新学科。七十年代我国开始开发应用,目前已广泛应用于电子领域中。在电路设计、分析、绘图、大规模集成和通道布线等方面均采用了技术,提高设计工效倍以上,经济效益十分明显。特别在大规模网络的设计,分析、集成工艺,优化技术和非线性系统分析中,已到非它不行的地步。1.2电子线路基本过程介绍一下基本过程: 给出任务和要求; 确定电路的性能指标; 设计电路的拓朴结构(元件之间的连接关系); 线路分析(对电路参数进行计算); 精细设计(元件参数的精细计算、功率、电压、电流参数的确定,最后用最优化技术确定一级最优电路参数); 输出结果(布线,原理图、印刷电路图,各种计算数据等); 分析结果。2. 系统开发2.1c+的诞生在1979年4 月到10月的这段日子里,bjarne stroustrup萌生了把开发一种工具变为开发一种语言的想法。在1983 年12 月,bjarne stroustrup 正式把cwith classes 命名为c+visual c+ 全称是 microsoft visual c+, 即微软的 c+ 和c的编译器。 用visual c+写程序,即用微软的c+语言写程序,可以调用微软的c+ 的mfc等程序库,应用微软的c+ 的头文件。2.2windows 图形编程基本技术windows 操作系统的图形界面有目共睹,几乎输出到屏幕上的东西都是图形,包括文本在内。windows提供给编程者大量图形相关的函数,这些。windows通过个称作设备上下文()环境来决定图形输出时的一些参数,包括硬件设备的各个属性值、坐标系的情况、颜色情况等,从而实现设备无关性。2.2.1 图形设备接口()图形设备接口(gdi,graphics device interface)的主要目标之一是支持在输出设备(如视频显示器、打印机和绘图仪)上的与设备无关的图形,是windows提供的一个关于图形操作的抽象的接口。通俗地讲就是各种关于图形操作的函数库。我们的程序可调用该接口中的函数实现对图形线条的粗细、图形的颜色、填充颜色及形状等图形属性设置,也就是说通过间接地和硬件打交道,而不像编程那样考虑直接往视频存储区或打印机端口输入数据,从而实现设备无关性。windows不允许应用程序直接访问显示硬件,必须通过和特定窗口相关联的“设备环境”跟显示硬件进通讯,因此函数会自动参考被称为“设备环境”的数据结构进行绘制。中包括各种绘图对象,如画笔、画刷、字体等,这些绘图对象就像画家工具箱中的各种画图工具。 gdi通过将应用程序与不同输出设备特性相隔离,使windows应用程序能够毫无问题地在windows支持的任何图形输出设备上运行。windows中的图形基本上是由从gdiexe模块中输出的函数处理的(尽管一些绘制函数实际上具有userexe的入口点),gdiexe模块调用在不同驱动程序文件中的例程,其中有一个drv驱动程序文件用于控制显示屏幕,并且可能有一个或多个其他的drv驱动程序文件用来控制打印机或绘图仪。windows gdi使用两种坐标系统。使用虚拟坐标系统可以使程序不依赖于具体的硬件,使用设备坐标系统可以使程序和硬件紧密相联。gdi含有在windows应用程序内部执行、且与设备无关的图形操作函数,这些函数可产生各种各样的线、正文和位图,它们可以输出到许多不同的输出设备上。gdi允许一个应用程序产生笔、刷子、字体和位图,以供特定的输出操作使用。下面列出gdi中几组比较常用的函数:设备上下文函数,椭圆和多边形函数,绘图工具函数,位图函数,绘图属性函数,正文函救,映射函数,坐标函数,元文件(metafile)函数,区域函数,裁剪(clipping)函数。窗口应用程序输出图形的操作步骤如下:取得指定窗口的当前显示设备上下丈,显示设备上下文实际上是一个数据结构,它包括该窗口的参数及各种图形、文字属性的现行设定值,它们对以后的图形、文字输 出命令起控制作用。选择用户坐标系及映射方式。设定用户坐标系中的观察窗口和设备坐标系中的显示视区。输出图形、文字和图象。释放所使用的显示设备上下文。当想要在图形输出设备(例如屏幕或打印机)上绘制图形时,必须首先获得设备上下文的句柄。先给出这个句柄,windows才允许程序使用设备,在gdi函数中将句柄作为一个参数传入,向windows标明需要使用的设备。设备上下文中包含许多属性,当gdi在不同的设备上工作时都要用到这些属性。使用这些属性可使gdi只关心起始和终止坐标的大小,而不必关心有关对象的其他属性,如颜色、背景等等,因为这些都是设备上下文的一部分。当需要修改这些属性时,只需调用一个修改设备上下文中属性的参数,以后的程序中都使用修改后的设备上下文属性。设备上下文是连接windows应用程序、设备驱动程序以及输出设备的纽带。2.2.2 设备环境设备环境,又称作设备上下文(device context),或者叫做设备述表,是windows gdi中的一个非常重要的内容,它不公可以绘制各种图形,而且还可以确定在应用窗口中绘制图形的方式,比如绘图模式和映射模式。应用程序在绘图之前,必须获取绘图窗口的设备环境,接着才去调中具体的绘图函数,这样函数才会根据已经获取到的进行图形的绘制。windows的设备环境是gdi关键元素,它代表了不同的物理设备,分为4种类型: 显示器型:支持视频显示器上的绘图操作 打印机型:支持打印机和绘图仪上的绘图操作 内存型:支持位图上的绘图操作 信息型:支持设备数据的访问2.3 mfc 中与图形相关的类介绍mfc针对windows中关于图形相关的类介绍mfc针对windows中关于图形操作方面的进行了面向对象的封装,以类形式捍供给开发者,mfc 中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来建立windows下的应用程序,为图形编程提供了方便。mfc的类中与图形操作相关的类主要分两种:一种是cdc类,一种是gdi对象类。下面详细介绍这些类。2.3.1 cdc类图形和文本的绘制需要用到mfc的cdc类,它是一个设备环境类。所谓设备环境,就好比我们写字用的纸那样,显示时指的是屏幕,打印时指的是打印机。实际上,mfc的cdc类还为一些特殊的设备环境提供相应的派生类。简单地说,cdc类主要完成绘图功能和环境的建立。也就是说,当需要绘制直线、绘制圆或椭圆、绘制正方形等图形时,从cdc类中可以找到答案;当需要改变绘图的环境,包括图形的颜色、画笔的粗细、坐标系的从标轴方向及原点的位置等,从cdc类也可以找到答案,不地有些情况(如图形的颜色、画笔的粗细等环境)需要和gdi对象类合作完成工作。表给出cdc类中常用的成员函数名称及函数功能说明。函数名称功能说明textout()绘制文本lineto()绘制线条moveto()设置画笔的位置ellipse()绘制椭圆或圆(根据给定的外切矩形的情况而定)arc()绘制图标rectangle()绘制矩形bitblt()把位图从一个拷到另一个draw3drect()绘制三维矩形drawicon()绘制图标fillrect()用给定的画刷的颜色填充矩形getmapmode()获取当前的映射模式gettextcolor()获取文本的颜色pie()绘制饼图polygon()绘制多边形selectobject()选取gdi绘图对象selectstockobject()选取库存的对象setmapmode()设置映射模式setviewportorg()设置视口中坐标系的原点setwindowext()设置窗口的范围setviewportext()设置视口的范围lptodp把点的坐标从逻辑坐标转换为设备坐标dptolp()把点的坐标从设备坐标转换为逻辑坐标类的成员函数还有很多就不一一列出 派生类在mfc中,类派生了以下几个类:cclientdc,aintdc,cwindowdc,cmetafiledc使用cwindowdc方法(1)对于显示器类型的第一步:调用*cwnd:getdc()函数来获得指向窗口的工作区的指针。如果需要在窗口的非客户区使用cwindowdc,这时需要调用getwindowdc()函数获得设备环境。第二步:利用第一步中得到的dc指针,调用cdc类的函数,来完成一些绘制工作。第三步:释放获得的,使用releasedc()(2)对于打印机类的对于打印机类型的而言,默认情况下windows没有创建起来,需要程序在使用时创建,而不是使用getdc()这样的函数获得。第一步:调用cdc*cwnd:createdc()函数来创建指向打印机设备的dc对象。第二步:利用第一步中得到的对象,调用cdc类的函数,来完成一些绘制工作。第三步:删除创建的dc,使用deledc()(3)对于内存型的dc第一步:调用cdc*cwnd:createcompatibledc()函数来创建兼容设备环境。第二步:利用第一步中得到的对象,调用类的函数,来完成一些绘制工作。第三步:删除创建的,使用()2.3.2 gdi对象类gdi对象类主要是一些绘图工具类,就像画家的工具箱,放置了各种各样的画图工具。对象的创建,cpen、cbrush两个类提供了构造函数直接创建的方法,而其他类的创建是不能仅仅依靠构造函数的创建来完成的,还需要通过类中提供的createfont、createrectrgn等函数来完成真正的创建工作。2.3.3 cdc类和gdi对象类合作当获取了当前cdc类的对象或者指向对象的指针,进行实际的图绘制时,如果需要改变画笔的颜色、线条的宽度等属性,那么就需要使用到cdc类中的selectobject()函数。这个函数用位图、画笔、画刷等gdi对象选入设备环境中,用新的对象替代同一类型的老对象显然对dc更改需要两个类的合作,首先要创建新的画图工具,也就是gdi对象,创建方法就是使用前面讲到的gdi对象创建方法,包括构造函数创建的方法和非构造函数创建的方法。然后利用cdc类的selectobject()函数把创建好的画图工具选入设备环境中,这样再次进行画图时,将利用新的画图工具画图。2.3.4 坐标变换和映射模式windows中有两种坐标,一种是设备坐标,一种是逻辑坐标,所谓映射模式就是指这两种坐标系在相互换时,逻辑单位和设备单位之间存在的某种比例关系。以显示像素做为单位时,我们称为设备坐标。在某种特定的映射模式下的坐标称为逻辑坐标。以上介绍的这几种映射模式中,mm_lometric, mm_himetric, mm_longlish, mm_heenglish, mm_twips被称为“固定比例”的映射模式,它们用的坐标系都是笛卡儿坐标系(x轴向右递增,y轴向上递增),唯一不同的是设备坐标向逻辑坐标转换时的比例关系。mm_isotropic、mm_anisotropic两种映射模式被称作是“可变比例”的,我们可以利用这个可变性,通过改变比例因子和坐标原点来实现图形的放大缩小和移动。我们通过改变x轴和轴的比例关系,可以将圆改变为椭圆。2.3.5 onpaint()和ondraw()下面我们来分析这两个函数。:onpaint()成员函数是wm_paint消息的消息映射函数,写在这个函数中的绘图代码,只能显示在屏幕而不能输出到打印机上,关于打印机的输出需要应用程序编写代码方能完成。cview:ondraw()成员函数从严格意义上讲,不是wm_paint消息的消息映射函数。可是在mfc中大多数情况下,我们的绘图代码应该写到这个函数中去,既然它不是wm_paint消息的消息映射函数,能保证屏幕的完整性吗?经过实验我们发现,在保证屏幕的完整性方面它和onpain()没有任何区别,那么mfc为什么增加这么一个函数呢,直接使用onpaint()不就可以了吗!下面我们来分析这两个函数:共同点:都能在wm_paint消息发生时被调用,从而都能保屏幕完整性。不同点:onpaint()只能将图形输出到屏幕上,而不能输出打印机上;ondraw()中的图形不仅可以输出屏幕上,而且还能将图形输出在打印机上。当输出到屏幕上的内容和输出到打印机上的内容一致时,在ondraw()写代码更方便。因此,一般情况下,在视图中实现绘图的代码应该写在ondraw()函数中,而不是写在onpaint()函数中。2.4序列化常见的有两种:一种是二进制文件的形式,另一种是数据库方式。在本系统中采用前一种,下面我们将对mfc中提供文件的操作进行介绍。2.4.1序列化概念序列化实际上就是让对象可以持续,当程序退出时他们可以存盘,当程序重新启动时可以被恢复。对象的这种存盘和恢复的过程就称为“序列化”。序列化和数据库:不能试图用序列化来代替数据库管理系统。2.4.2序列化机制中提供了两种文件操作的方法,一种是直接使用cfile类的方法,一种是使用carchive类的方法。这里我们讲的是第二种方法。本来在mfc库中提供了cfile类来表示磁盘文件,应用程序可以通过这个类进行文件的读写操作。不过mfc提供的序列化机制可以避免我们直接与磁盘i/o打交道,它是在序列化函数(serialize)和cfile对象之间加入了一个carchive桥梁。这个carchive对象为cfile对象缓存数据,它同时还保存了一个内部标记,用来表示归档是存入还是载入。当需要将数据交给carchive类对象,当需要从文件中读出数据时,也是向carchive对象索要数据。总之,carchive就是应用程序和文件的一个桥梁。更重要的是mfc提供的这种序列化机制可以实现类对象这样的复杂数据的序列化,只要按照下面的所讲的类序列方法,将对象所属的类加入序列化方法即可。2.4.3实现类的序列化类序列化方法第一步:从cobject或其派生出自己的类,也就是要序列化的类。第二步:重载serialize()成员函数,加入必要的代码,用以保存对象的数据成员到carchive对象及从carchive对象载入对象的数据成员状态。第三步:在类声明文件中,加入declare_serial宏。编译时,编译器将扩充该宏,这是串行化对象所必需的。第四步:定义一个不带参数的构造函数。第五步:在实现文件中加入implement_serial宏。2.4.4文档、视图架构程序中数据的序列化文档、视图架构是visual c+工程的一种非常重要的组织方式,也是当前设计模式领域中模式中的一种具体应用。在这种架构中,视图类的主要职责就是显示,文档类的职责就是存放数据。对于整个工程来说,数据存放在文档类中,那么序列化就是要对文档类中的数据进行的,而不是对其他类中的数据。这就给我们提出了一个问题:文档类中的数据如何实现序列化?答案非常简单:把序列化工作放在cdocument派生类的serialize()函数中进行。这个函数的调用执行过程为:第一步:打开文件对话框,提示用户选择要打开的文件;第二步:调用已经存在的文档对象的cdocument:onopendocument虚成员函数。该函数将打开文件,并调用deletecontents函数,之后再创建一个用于装入数据的carchive对象。然后调用文档类的serialize函数,从归档中载入数据。第三步:调用视图的oninitialupdate函数。这个函数将导致cview:onupdate()的执行。2.5电子线路绘制系统的需求分析。2.5.1绘制功能概述:这个部分是整个系统的主要功能,要求在系统中以各种电子元件器件工具的形式给出,而不是提供图形的基本元素比如直线,点等。用户只要选择了其中的某个器件工具,其实就是示意图,然后只要用鼠标在屏幕上的某个位置点按一下,那么这个器件图就可以绘制在这个位置上。然后根据电路原理对器件进行连接,画出一幅电子电路图。操作方式:需要提供工具栏和菜单两种操作方式。提供绘制“二极管”、“三极管“、”电阻“、”电容“、”电感“”三端电源“芯片”“平行插座”“交错插座”“开头”十种电路板上常用元器件的绘制工具。当通过选择某个菜单或工具栏中的某按钮改变了当前绘制的器件类型时,还要求能通过改变鼠标的形状来示意当前的状态。用鼠标点按的方式绘制出的器件图,要按照序号递增的方式,给出默认的器件名称,具体地讲,就是要根据当前已经绘制出的某种类型的器件的个数来决定当前这个器件的名称。举例来说,假如目前已经绘制出的个电阻,那么再次绘制电阻的话,它的名称应该是,当然,也可以进行重新编辑。2.5.2图形编辑功能概述:当使用系统提供的器件图工具绘制出器件的示意图后,要求能够对意图进一些简单的编辑,那么图形编辑的功能主要包括以下几个部分:放在缩小修改颜色3移动位置4置前、置后5编辑线型6删除7复制和粘贴选取2.5.3器件属性的编辑对于一个电路板上的元器件而言,它具有两方面的属性,一方面是它作为电子元器件的物理属性,比如,电阻有阻大小,电阻的类型、电阻在电路板上的名称等。另一方面是它作为器件示意图所具有的属性,比如颜色、位置等。这里的编辑功能是指对物理属性的编辑,关于第二方面的属性编辑,在前面的“图形编辑功能”中已经提到了。操作方式:以对话框的方式提供给用户。器件物理属性器件名称属性二极管二极管的类型、功率、开关、频率三极管三极管的功率、频率、类型电感电感的工作频率、电压、功耗、容量电容电容的电压、类型、容量、工作频率ic芯片封装形式、管脚数目、正常电流、正常功耗插座的插座的正常电流、类型、正常电压开关类型三端电源第一端电压、第二端电压、第三端电压、标准输出、电压、正常工作电压22.5.4保存器件图,电路图对画出的图进行保存。2.6重点功能实现方法(具体代码见附件)2.6.1绘制器件图绘制系统的一个关键问题是如何把各种常见元器件示意图绘制到绘图区域,是使用贴图的形式,还是矢量图的方式?这就要看用户的要求了。本系统我们选择了后者。常用元器件的示意图,可根据前面系统分析与设计,一节中设计出的比例关系进行绘制。具体的绘制方法,是利用本章介绍的windows图形编程知识和图形编程类来完成绘制。不同器件的示意图有着不同的外观,只有决定了器件的类型才能决定示意图(是电阻还是三极管)。因此,绘制过程是由系统分析与设计一节中设计的具体的器件类的绘制成员函数来完成的,而不是在基类(ccomponent)中,但是所有具体的器件类的基类应该提供一个统一的绘制接口,因此把绘制功能作为虚成员函数定义在基类中,派生类继承后重载这些虚函数。把绘制函数制作为一个基类的虚函数,最为明显的一个好处是使用基类的指针调用派生类的函数,这正是语言中虚函数的用意之所在。函数定义:ccomjponent:draw函数定义为虚函数 class ccomponent:public cobject virtual void ccomponent:draw(cdc *pdc)接下来,我们给出三极管类的绘制功能函数,其他类的实现原理同三极管,只是画的线段不同。2.6.2选择器件图为了实现器件图形的放大、缩小、器件图形的移动、器件的删除、器件属性的编辑等功能那么前提条件就是必须确定移动的是哪个器件、删除的是哪个器件、编辑的又是哪个器件,因此,如何选择器件就成了实现以上功能首要问题。用户选择了某个或某些器件后,如何来标记这个器件已经处于选择状态。根据常见的可视化开发工具,比如、,其中对话框(或成为)中一个一个的控件图形选择状态,是用将原来图形的矩形区域边缘加入一些小实心矩形来表示的,那么我们这里可以借鉴这种办法,但是如何实现?我们可以全部自己来开发这部分代码,步骤就是:利用crect:ptinrect()函数来判断鼠标点按的位置,如果在器件图所在矩形区域,那么将原来的器件图所在的矩形区域的外围绘制出实心小矩形;如果鼠标没有点按在器件图所在的矩形区域,则不作任何动作。问题是如何绘制出这些实心小矩形吗?处于选择状态的器件图的放大缩小又如何实现为前面提到的可视化开发工具中控件图的放大缩小效果呢(鼠标拖控件图的矩形边缘将图形平滑放大缩小)?答案是肯定的。我们可以自己开发,但我们发现已经封装了一个完成此功能的类crecttracker.。我们就使用它来完成,这样会省去不少的代码量,选择使用现在的类也是我们进行项目研发的一个较好的策略。本系统中“选择器件图”“器件图放大、缩小”单个器件图移动“功能均由crecttracker类来完成,下面首先对crecttracker类进行详细的介绍,然后对本系统单选和多选器件图功能实现进详细的讲解。()crecttracker类crecttracker类是mfc提供的一个ole类,不过它可以很方便地应用于ole应用程序和非ole应用程序中。它的主要功能是实现对视图中某个矩形区域的跟踪,当鼠标点扫在被跟踪的矩形区域后,整个鼠标的消息将会全部被crecttracker类控制。也就是说这个类拥有消息的分发机制,当鼠标左键按下,并且移动鼠标时,如果鼠标点按的位置处于矩形区域的内部,那么crecttracker类将会完成矩形区域的移动;如果鼠标点按的位置处于矩形区的边缘,那么crecttracker类将会完成矩形区域的移动、放大,缩小。并且可以通过设置某些数据成员的值,来改变鼠标移动到被跟踪的矩形区域的内部和边缘时鼠标的形状。下面对crecttracker类中一些常用的数据成员及成员函数进行说明:m_rect: crecttracker类跟踪的矩形区域。m_nstyle:crecttracker类的风格,可以是合法的值及每种值所对应的crecttracker类的draw函数绘制出的矩形示意图。crecttracker:solidline:矩形边缘用实线绘制crecttracker:dottedline:矩形边缘用点画线绘制crecttracker:hatchedborder:矩形边缘用斜线绘制crecttracker:resizeinside:矩形边缘内部用小方框绘制crecttracker:resizeoutside| crecttracker:solidline:矩形边缘的外部用小方框绘制crecttracker:hatchinside:矩形的内部用斜线绘制track()函数:crecttracker类的这个函数从鼠标点按在被跟踪的矩形区域开始到鼠标键抬起,一直控制鼠标消息,这一点和cdialog:domodal()函数相同,这也正是它的神奇之处。draw(cdc*pdc)绘制出被跟踪矩形,即m_rect,绘制的模式由m_nstyle而定。int hittest(cpoint point):测试鼠标点按的点是否在m_rect定义的矩形区部或边界线上。crecttracker m_tracker;crect m_recttrackerctestview:ctestview() m_recttracker.left=10;m_recttracker.top=10m_recttracker.bottom=200m_recttrack.ringt=200m_tracker.m_nstyle=crecttracker:resizeinside|crecttracker:dottedlinevoid ctestview:ondraw(cdc*pdc)pdc-rectangle(m_recttracker)this-m_tracker.m_rect=this-m_recttrackerpdc-lptodp(this-m_tracker.m_rect)this-m_tracker.draw(pdc)void ctestview:onlbuttondown(uint nflags,cpoint point) if(m_tracker.track(this,point,false,null) cclientdc dc(this) onpreparedc(&dc) m_recttracker=m_tracker.m_rect dc.dptolp(m_recttracker) invalidate()cview:onlbuttondown(nflags,point)(2)单选其实,学习了crecttracker类之后,本功能的实现就非常容易理解了具体步骤为:第一步:利用crecttracker:hittest()函数测定鼠标是否点按在某个器件图所属的矩形区域内。如果返回值不是crecttracker:hitnothing,并且没有按下shift键,那么属于单选,进行第二步。这一步本系统制作了一个cdrawchipview类的成员函数isinchiprect(),函数原型为bool cdrawchipview:isinchiprect(cpoint point,coblist*poblist,position *pcurpos,bool*pissel)第二步:在cdrawchipview的wm_lbuttondown的消息映射函数中,将被选中器件的m_isselected数据成员,利用所有器件类的基类ccomponent:setisselected()成员函数,将其设置为true,并且调用invalidate(),产生消息,触发第三步ondraw()的执行。第三步:在cdrawchipview:ondraw()中,将存放在器件链表中所有处于选中状态的器件图,利用crecttracker:draw()函数将器件图所属的矩形区边缘绘制出(m_nstyle设置为crecttracker:resizeoutside).当然,如果没有处于被选中状态,就不进行crecttracker:的调用,因此选中和没被选中的器件图在图的矩形边缘上就区别开了。()多选多选的实现步骤和单选功能基本相似,不同之处在于,当按下键上的shift键时,表明当前处于多选状态,那么,当鼠标点按在某个器件图上时,单选是把其他所有器件对象的m_isselected数据成员设置为false,仅把当前选中的器件对象的此数据成员设置为true.而多选并不去改变其他器件对象的m_isselected属性,只是把刚选中的器件对象的m_isselected设置为true.2.6.3器件图的放大、缩小、单个器件图的移动这几个功能的实现就是使用上面讲到的crecttracker类的track来完成的。因为当使用了crecttracker类对象将器件图所在的矩形域进行track后,一旦鼠标点按在矩形区域的边缘,然后进行鼠标移动,并且没有松开鼠标。crecttracker类将会对它所跟踪的矩形进行放大、缩小,同时改变crecttracker类的m_rect的值来调整器件图所在的矩形区域,不过有一点一定要注意,m_rect放的是设备坐标,在将它作为器件图所在的矩形区域之前必须进行设备坐标向逻辑坐标转换。具体实现代码在cdrawchipview的wm_lbuttondown消息的消息映射函数onlbuttondown中,下面给出本函数中的代码片断。2.6.4器件图的_order顺序调整当绘制区内的几个元器件图形叠放在一起时,有的图形被其他图形遮挡住了,而这时双想迁取被挡住的器件,这就需要将挡在它前面的器件图形置后;当几个器件图形叠放在一起,但不是全部叠放,这时可以对其中的任意一个器件图形进行选择,但是被选择的器件图形由于被其他器件图形盖住了一部分,因此不能全部显示,这时需要将这个被选择的图形置前。这里的置前置后操作就是改变器件的_order顺序。具体实现的方法要从整个程序的数据结构来考虑,在本系统中所有绘制的器件对象存放在coblist类对象中,即链表,并且在cdrawchipview:ondraw()函数中是按照链表由前往后画的器件将压在先画的器件之上。改变器件图的_order顺序2.6.5复制、粘贴复制和粘贴功能的实现要依靠windows前贴板,windows的剪贴板实质上是一块内存空间,而且是一块对各个进程都透明的内存空间。当我们将数据存放到剪贴板上时,申请空间应该使用windows的函数:hglobal globalalloc(uint nflag,size size),并且使用globallock()函数将申请的内存锁住,且返回指向内存的指针。复制和粘贴的过程从某种意义上来讲是序列化。下面首先给出复制和粘贴的一般步骤,然后对本系统中此功能的实现进行详细讲解。一般步骤(1)复制功能的步骤注册剪贴板格式,使用函数原型为:uint registerclipclipboardformat(lpctstr lpszformat/name of new format)打开剪贴板,使用的函数原形为:bool openclipboard(hwnd hwndnewowner/handle to window)清空剪贴,使用的api函数原形为:bool emptyclipboard(void)申请内存,使用的api函数原型为:hglobal globalalloc(uint uflags,size_t dwbytes)将申请内存加锁,使用的api函数原型为:lpvoid globallock(hglobal hmem/handle to global memory object)将数据拷入内存void *memcpy(void *dest,const void *src,size_t count)将内存解锁,使用的api函数原型为bool globalunlock(hflobal hmem/handle to global memory object)将内存中的数据放到windows的剪贴板上,使用的api函数原形为:handle setclipboarddata (uint uformat,/clipboard format handle hmem/data handle)关闭剪贴板,使用的api函数原型为:bool closeclipboard(void)(2)粘贴的步聚为:打开剪贴板将剪贴板上的数据拷入内存,使用的api函数原型为handle setclipboarddata(uint uformat/clipboard format)将内存中的数据拷入某个变量关闭剪贴板。2.6.6载获windows的消息实现多个器件图的移动windows是一个消息驱动的操作系统,这也正是它的精华之所在。既然如此,真正的windows编程就应该充分利用和体现这一点。要实现消息驱动的话,我们需要自定义消息,然后在某种情况下产生此消息并发送。这样程序中相应的此消息的处理函数在收到此消息后,自动地被调用。windows的消息机制固然很好,但是它并不是在任何情况下都体现为优点。比如在多种消息发生时,需要集体处理的情况,它就显得有些束缚手脚。这时候就需要拦载windows本身对这些消息的处理,自行处理。2.6.7实现器件之间的连接线本例画线连接位图器件实现步骤:一、基本使用函数1.onpaint和ondraw函数view的父类的onpaint函数调用了ondraw函数,若在子类为wm_paint消息添加响应函数onpaint,ondraw函数将不会被调用。2cpaintdc和cclietndccpaintdc的构造函数中调用了beginpaint(),析构函数中调用了endpaint();cclietndc的构造函数中调用了getdc(),析构函数中调用了releasedc()。而beginpaint(),endpaint()只能用于响应wm-paint消息,否则将会出错。二、利用动态数组:1定义结构体line,用于保存线的数据。struct linecpoint m_pt1;cpoint m_pt2;2在view中定义一个动态数组,保存每一根线的指针。cptrarray m_ptrlines;定义两个cpoint的成员变量,保存线的起点和终点: cpoint m_ptold; cpoint m_ptnew;3在view中加入wm_lbuttondown,wm_lbuttonup的响应函数,在onlbuttondown中为m_ptnew赋值,m_ptold=point;4在onlbuttonup中加入代码:m_ptnew=point;cclientdc dc(this);dc.moveto(m_ptold);dc.lineto(point);line *pln=new line;pln-m_pt1=m_ptold;pln-m_pt2=m_ptnew;m_ptrlines.add(pln);5在ondraw()中加入:int sum= m_ptrlines.getsize();for(int i=0;ipdc-moveto(line *)m_ptrlines.getat(i)-m_pt1);pdc-lineto(line *)m_ptrlines.getat(i)-m_pt2);6加入滚动条:将view的cpp文件和h文件中的cview全部替换成cscrollview。7在view中加入虚函数oninitialupdate(),这个函数在view第一次刷新前被调用,在其中加入代码:setscrollsizes(mm_text,csize(1024,768);这个函数也可在view的构造函数中调用。8在onlbuttonup中生成dc后加入onpreparedc(&dc); dc.dptolp(&m_ptold); dc.dptolp(&m_ptnew);三、利用cmetafiledc重绘1在view中定义成员变量:cmetafiledc m_dcmetafile;2在view的oncreate中加入代码:m_dcmetafile.create();3在view的onlbuttonup中,注释有关数组的代码,加入:m_dcmetafile.moveto(m_ptold);m_dcmetafile.lineto(m_ptnew);4在ondraw()中hmetafile hmetafile; hmetafile=m_dcmetafile.close(); pdc-playmetafile(hmetafile);m_dcmetafile.create();m_dcmetafile.playmetafile(hmetafile); :deletemetafile(hmetafile);5保存文件:加入菜单响应函数,onfilesave,加入代码: hmetafile hmetafile; hmetafile=m_dcmetafile.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 一个十人网络管理制度
- 不断推进会计管理制度
- 专业指导委员管理制度
- 壮锦文创产品设计
- 社会科学研究课题参考
- 新能源汽车专业职业生涯规划书4800字数
- 药检室仪器设备管理制度
- 严格执行收费管理制度
- 临床药师绩效管理制度
- 美容业公司企业管理制度
- 5-1贯入法砌筑砂浆砂浆抗压强度检测方案
- 锚杆加固施工方案(通用版)
- 海水的淡化精品课件
- 地源热泵埋管冬夏季换热平衡计算
- 甲骨文专‖教学课件
- 规章制度和操作规程的管理制度范本
- 形式发票格式2 INVOICE
- 清华大学美术学院陶瓷艺术设计系研究生导师及研究课题
- 理论力学运动学题库
- 计算机控制实验报告初稿(共31页)
- 2012年内蒙古鄂尔多斯市中考物理试卷【含答案可编辑】
评论
0/150
提交评论