1 / 118

VC++ 入门与提高

VC++ 入门与提高. 主讲教师:贾澎涛. 第七章应用实例之二 —— 开发一个简单的矢量图形系统. 本篇经典 什么是矢量图形和栅格图形? 矢量图形系统应具有的功能? 与图形操作有关的 MFC 类有哪些? 如何实现基本矢量图形的文档和视图? 如何实现鼠标交互绘图? 参考教材: 《Visual C++ 开发 GIS 系统 》 陈建春编著. 7.1 什么是矢量图形和栅格图形?. 目前用计算机绘制和存储图形,主要有两种形式: 栅格图形 和 矢量图形 。

casper
Download Presentation

VC++ 入门与提高

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. VC++ 入门与提高 主讲教师:贾澎涛

  2. 第七章应用实例之二——开发一个简单的矢量图形系统第七章应用实例之二——开发一个简单的矢量图形系统 本篇经典 • 什么是矢量图形和栅格图形? • 矢量图形系统应具有的功能? • 与图形操作有关的MFC类有哪些? • 如何实现基本矢量图形的文档和视图? • 如何实现鼠标交互绘图? 参考教材:《Visual C++开发GIS系统》陈建春编著

  3. 7.1什么是矢量图形和栅格图形? 目前用计算机绘制和存储图形,主要有两种形式:栅格图形和矢量图形。 • 栅格图形也称点阵图形,是由一个个像素组成的图形,局部放大图形会出现马赛克现象。点阵图形能纪录下图像无规律的微妙层次变化,通常是一些纪实的照片,但不适合用来描述需要进行变化的图形。 • 矢量图形的图像是以曲线及节点来表示图形,图形的位置通常通过一些函数得到,可以无限放大而不影响其精度,但矢量图形并不适用于纪录真实、层次变化复杂的图像。 • 矢量图形和点阵图形放大的比较如下表所示。

  4. 原图 局部放大后 点阵图形 >>> 矢量图形 >>>

  5. 7.2矢量图形系统应具有的功能? • 相对完善的图形元素。具备处理点、直线、圆、连续直线、多边形区域、标注文本等图形元素的能力,并具有处理图例(即图形块)的能力。 • 相对完善的图形操作功能。具备图像的缩放、移动、回溯等各种操作功能。 • 相对完善的图形输入和输出功能。具备鼠标交互绘制、图形数据交互输入、等功能。系统还具备从打印或绘图设备输出图形的能力。 • 具有图层、颜色、线形等的设置功能。 • 具有较大的存储容量。 • 较强的容错能力和可恢复性,具有较高的处理速度。

  6. 7.3与图形操作有关的MFC类有哪些? • 绘图类 绘图就要用到MFC类CDC、CClientDC、CPaintDC、CWindowDC等,其中CDC类是基础,另外几个类是为了特殊应用由其派生出来的。 • 绘图设备类 绘图设备类是一些已经定义的MFC类。通过这些绘图设备类定义的对象能够完成图形操作过程中的某类操作功能,可以将这些绘图设备类创建的对象选入到绘图类对象中,完成有关的操作。在MFC则把,主要有以下几个绘图设备类:CGdiObject、CPen、、CBrush、CFont、CRgn、CPalette、CBitmap。

  7. 7.3.1绘图类简介 • CDC类:因为CDC类不能用窗口指针初始化对象,所以一般不直接定义对象应用,但经常用来建立一个内存设备描述对象,创建方法如下: CDC dc; • CPaintDC类:CPaintDC类一般用在窗口类的OnPaint函数中,可采用如下代码定义一个CPaintDC类对象: CPaintDC dc(this); 以上代码定义了一个CPaintDc类对象dc,并用当前的窗口对象指针this对对象进行了初始化。 • CClientDC和CWindowDC也采用这样的使用方法。CWindowDC一般在框架类CMainFrame中使用。

  8. 7.3.2绘图设备类 • 通过绘图设备类定义的对象能够完成图形操作过程中的某类操作功能,可以将这些绘图设备类创建的对象选入到绘图类对象中,完成有关的操作。在MFC中,主要有以下几个绘图设备类:CGdiObject、CPen、CBrush、CFont、CRgn、CPalette、CBitmap。 • CGdiObject: CGdiObject是Cobject类的派生类,它为不同的Windows图形设备界面(GDI)提供了基类。 CGdiObject为它的派生类提供了大部分的操作,可利用这些派生类创建一个特定的GDI对象(如画笔、画刷、字体、位图等)。 CGdiObject类不能直接用来创建一个对象。

  9. Cpen类 • CPen是CGdiobject类的一个派生类,它模拟画笔图形设备界面。以下是CPen对象的创建和在绘图类对象中的引用方法。 • 创建CPen对象,有以下几种方法来创建一个CPen对象: • 定义一个CPen对象,用其成员函数CreatePen或CreatePenIndirect对其进行初始化。 CPen pen; Pen.CreatePen(PS_SOLID,1,RGB(255,0,0)) • 定义一个CPen对象,并一次性地初始化它的所有参数 CPen pen(PS_SOLID,1,RGB(255,0,0)); • 动态创建一个CPen对象 CPen *pen; Pen=new CPen (PS_SOLID,1,RGB(255,0,0));

  10. 在绘图对象中选入画笔 以在CMyView ::OnDraw(CDC* pDC)函数中操作为例,讨论在绘图对象中选入画笔即CPen对象的方法。 void CMyView::OnDraw( CDC* pDC ) { CPen pen(PS_SOLID,1,RGB(255,0,0)); CPen* pOldPen = pDC->SelectObject( &pen ); //省略各种绘制代码 pDC->SelectObject( pOldPen ); } 在CClientDC、CWindowDC等其它绘图对象中,可以用类似的方法来选入CPen对象。

  11. CBrush • 创建CBrush对象 • CBrush类有4个构造函数,现在只对主要的几个构造函数进行介绍。以下按照实心、影线及位图填充几类画刷来讨论Cbrush对象的创建过程。

  12. 实心画刷 用实心画刷进行填充时,以这种画刷的颜色实心填充。 • 一次性创建 CBrush brush(RGB(255,0,0) • 动态创建 CBrush *brush; Brush =new Cbrush(RGB(255,0,0); … delete brush; • 用函数CreateSolidBrush对对象进行初始化。 CBrush brush; brush.CreateSolidBrush(RGB(255,0,0)

  13. 影线画刷 • 影线画刷不是用画刷的颜色实心填充图形,而是填充不同的阴影图案。影线画刷的创建方法如同实心画刷。 • 一次性创建 CBrush brush(HS_HORIZONTAL,RGB(255,0,0) • 动态创建 CBrush *brush; Brush =new CBrush(HS_HORIZONTAL ,RGB(255,0,0); … delete brush; • 用函数CreateHatchBrush对对象进行初始化。 CBrush brush; brush. CreateHatchBrush(HS_HORIZONTAL ,RGB(255,0,0)

  14. 位图画刷 • 位图画刷用位图图像来填充图形,函数CreatePatternBrush用来初始化一个位图画刷。以下代码创建一个位图画刷,pBitmap指向一个位图对象: CBrush brush; brush.CreatePatternBrush(pBitmap);

  15. 在绘图对象中选入画刷 以在CMyView ::OnDraw(CDC* pDC)函数中操作为例,讨论在绘图对象中选入画刷即CBrush对象的方法。 void CMyView::OnDraw( CDC* pDC ) { CBrush brush(HS_CROSS,1,RGB(255,0,0)); CBrush* pOldBrush = pDC->SelectObject( &brush ); //省略各种绘制代码 pDC->SelectObject( pOldBrush ); }

  16. CFont • CFont是CGdiObject类的一个派生类,它模拟字体。 • 创建CFont对象 • CFont类只有一个构造函数,定义一个CFont对象后,必须用成员函数CreateFont, CreateFontIndirect, CreatePointFont, or CreatePointFontIndirect 来初始化CFont对象的参数。

  17. CreateFont函数 BOOL CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

  18. CFont对象的选用 void CMyView::OnDraw( CDC* pDC ) { CFont font; Font.CreateFont(30,15,0,0,200,0,0,0,255,0,0,2,DEFAULT_PITCH,”VC”); CFont* pOldFont = pDC->SelectObject( &font ); //省略各种绘制代码 pDC->SelectObject( pOldFont ); }

  19. 7.4如何实现基本矢量图形的文档和视图

  20. 7.4.1组织矢量图形系统的图形元素类 • 利用面向对象的程序设计和C++类的组织方法,组织建立起一个基本矢量图形系统的图形元素类。该矢量图形系统,能够处理直线、连续直线及多边形、圆及圆形区域、圆弧、标注文本等几类基本图形元素。针对每类图形元素组织建立起对其组织管理的C++类,吧每个图形元素作为独立的对象来管理。对各种图形元素进行分析,可得到如下的图形元素类结构体系。

  21. 图形元素基类的组织 class CDraw:public Cobject //基本图形类,用来存储图形的颜色、线型、层等信息 { protected: CDraw(){} //构造函数 short m_ColorPen; //笔色 short m_ColorBrush; //填充刷颜色 short m_LineWide; //线宽(像素) short m_LineType; //线型(像素) short m_Layer; //所处层 int m_id_only; //图形元素唯一的识别号 BOOL b_Delete; //是否处于删除状态

  22. public: CDraw(short ColorPen,short ColorBrush,short LineWide, short LineType,short Layer,int id_only,BOOL Delete) //构造函数 { m_ColorPen=ColorPen; m_ColorBrush=ColorBrush; m_LineWide=LineWide; m_LineType=LineType; m_Layer=Layer; b_Delete=Delete; m_id_only=id_only; } };

  23. (1)直线类组织 class CLine:public CDraw //直线类 { protected: float m_X1,m_X2,m_Y1,m_Y2; //直线的起点和终点 public: CLine(){} //不带任何参数的构造函数 //以下是有初始化参数的构造函数 CLine(short ColorPen,short ColorBrush, short LineWide,short LineType,short Layer,int id_only, BOOL Delete,float X1,float Y1,float X2,float Y2) :CDraw(ColorPen,ColorBrush,LineWide,LineType,Layer,id_only,Delete)

  24. { m_X1=X1; m_Y1=Y1; m_X2=X2; m_Y2=Y2; } };

  25. (2)连续直线和封闭多边形类组织 • 连续直线除了具有图形元素基类的所有属性外,从图形的几何特征上,连续直线是由很多顶点组成的。顶点的数目是不确定的,因此定义如下的结构来存储连续直线的一个顶点坐标: typedef struct { float x; float y; float z; }PointStruct;

  26. class CPline:public CDraw //连续直线或多边形区域类 { protected: int m_Numble; //连续直线或多边形区域的顶点数 BOOL b_Fill; //是否为连续直线 public: PointStruct* m_PointList; //存储顶点的数组指针 CPline() //不带任何参数的构造函数 { m_Numble=0;} CPline(short ColorPen,short ColorBrush, short LineWide,short LineType,short Layer,int id_only, BOOL Delete,int Numble,PointStruct* PointList,BOOL Fill) :CDraw(ColorPen,ColorBrush,LineWide,LineType,Layer,id_only,Delete)

  27. { m_Numble=Numble; b_Fill=Fill; m_PointList=new PointStruct[Numble+1]; //分配空间 if(Numble>0) { for(int i=0;i<Numble;i++) m_PointList[i]=PointList[i]; } } ~CPline() //析够函数 { if(m_Numble>0) delete m_PointList; } };

  28. (3)圆类组织 class CCircle:public CDraw //圆及圆形区域类 { protected: float m_CircleX,m_CircleY,m_CircleR; //圆心及半径 BOOL b_Fill; //是否填充,1-圆形区域 0-普通圆 public: CCircle() //不带任何参数的构造函数 {} CCircle(short ColorPen,short ColorBrush, short LineWide,short LineType,short Layer,int id_only, BOOL Delete,float CircleX,float CircleY,float CircleR,BOOL Fill) :CDraw(ColorPen,ColorBrush,LineWide,LineType,Layer,id_only,Delete)

  29. { m_CircleX=CircleX; m_CircleY=CircleY; m_CircleR=CircleR; b_Fill=Fill; } };

  30. (4)圆弧类组织 class CArc:public CCircle //圆弧类 { protected: float m_Angle1,m_Angle2; //圆弧的起点和终点角度 public: CArc() //不带任何参数的构造函数 {} CArc(short ColorPen,short ColorBrush,short LineWide ,short LineType,short Layer,int id_only,BOOL Delete,float CircleX ,float CircleY,float CircleR,BOOL Fill,float Angle1,float Angle2) :CCircle(ColorPen,ColorBrush,LineWide,LineType,Layer,Delete,id_only,CircleX,CircleY,CircleR,Fill)

  31. { m_Angle1=Angle1; m_Angle2=Angle2; } };

  32. (5)标注文本类 图形中有大量的标注文本,标注文本除了具有图形元素的基本特征外,还具有位置、字体及标注内容等自身的信息。 class CText:public CDraw //标注文本类 { protected: float m_StartX; //文本起点横坐标 float m_StartY; //起点纵坐标 float m_Angle1; //标注角度 float m_Angle2; //字体旋转角度 float m_TextHeight; //字体高度 float m_TextWide; //字体宽度 float m_OffWide; //间隔宽度

  33. unsigned char m_TextFont; //字体 CString c_Text; //标注的文本信息 int m_TextLong; //标注信息的长度 public: CText() //不带任何参数的构造函数 {} CText(short ColorPen,short ColorBrush,short LineWide ,short LineType,short Layer,int id_only,BOOL Delete,float StartX, float StartY,float Angle1,float Angle2,float TextHeight,float extWide,float OffWide,unsigned char TextFont,CString Text) :CDraw(ColorPen,ColorBrush,LineWide,LineType,Layer,id_only,Delete)

  34. { m_StartX=StartX; m_StartY=StartY; m_Angle1=Angle1; m_Angle2=Angle2; m_TextHeight=TextHeight; m_TextWide=TextWide; m_OffWide=OffWide; m_TextLong=Text.GetLength(); //计算字符的长度 c_Text=Text; } };

  35. (6)图形参数类 • 图形参数类用来管理诸如颜色、图层等方面的信息。 class CGraphPara //用来存储图形的基本参数的类 { protected: int n_ColorNumbAll; //总的颜色数 int n_LayerNumbAll; //总的图层数 int n_ColorNumb; //系统当前具有的颜色数 int n_LayerNumb; //系统当前具有的图层数 long* m_ColorList; //用来存储颜色列表 LayerStruct* m_LayerList;//用来存储层的列表

  36. public: CGraphPara() { n_ColorNumb=100; //最多具有100种颜色 n_LayerNumb=100; //最多具有100层 m_ColorList=new long[n_ColorNumb]; m_LayerList=new LayerStruct[n_LayerNumb]; n_ColorNumb=4; //目前有4种颜色 n_LayerNumb=1; //目前有一层 //以下初始化几种颜色和一个层 m_ColorList[0]=RGB(0,0,0); m_ColorList[1]=RGB(0,0,0); m_ColorList[2]=RGB(0,255,0);

  37. m_ColorList[3]=RGB(0,0,255); m_LayerList[0].b_Display=1; strcpy(m_LayerList[0].m_Name,"Layer 0"); } ~CGraphPara() { delete m_LayerList; delete m_ColorList; } public: COLORREF GetColor(int n); //得到第n种颜色的实际颜色 BOOL GetDisplayStatue(int n); //得到第n层的显示状态 };

  38. 7.4.2组织矢量图形系统的文档 (1)组织面向对象的文档存储管理机制 在这里,我们将讨论一套完整的面向对象的文档管理机制,通过图形元素类创建很多图形元素对象,每个图形元素对象作为一个整体来组织存储空间的分配、保存及读取等各种管理功能。通过建立一种存储机制,来管理指向所有图形元素对象的指针,达到管理所有图形元素对象的目的。这种文档管理机制具有组织简单、结构化和移植性好等优点。缺点是需要较大的内存空间。

  39. (2)利用MFC模板定义管理图形元素对象指针的对象(2)利用MFC模板定义管理图形元素对象指针的对象 管理一个矢量图形系统文档的思路是:每个图形元素是图形元素类创建的一个对象,在创建这个对象时得到指向这个对象的指针,通过建立一个对象指针数组来管理这些指针,来达到管理所有图形元素对象的目的。

  40. 在VC++下可以较容易的实现对指向图形元素对象指针的组织和管理。在MFC中有一个类模板CTypePtrArray,可以用它来定义一个管理类指针的对象。例如,可以定义一个管理CLine类指针的对象如下:在VC++下可以较容易的实现对指向图形元素对象指针的组织和管理。在MFC中有一个类模板CTypePtrArray,可以用它来定义一个管理类指针的对象。例如,可以定义一个管理CLine类指针的对象如下: CTypedPtrArray<CObArray,CLine*>m_LineArray; CTypedPtrArray定义的对象m_LineArray,由第一个参数指定的类(CObArray)创建且管理第二个参数指定的类指针。上述代码的含义是:对象m_LineArray由CObArray创建用来存放CLine指针。 • 在应用程序Draw中,可以派生几个CObArray对象来分别管理几类图形元素。

  41. 在文档类CDrawDoc中创建: private: CTypedPtrArray<CObArray,CLine*>m_LineArray; //管理直线对象指针的对象 CTypedPtrArray<CObArray,CPline*>m_PLineArray; //管理连续直线对象指针的对象 CTypedPtrArray<CObArray,CCircle*>m_CircleArray;//管理圆对象指针的对象 CTypedPtrArray<CObArray,CArc*>m_ArcArray; //管理圆弧对象指针的对象 CTypedPtrArray<CObArray,CText*>m_TextArray; //管理标注文字对象指针的对象

  42. 为了管理一个矢量图形的图形参数,在文档类CDrawDoc中定义一个CGraphPara对象:为了管理一个矢量图形的图形参数,在文档类CDrawDoc中定义一个CGraphPara对象: CGraphPara m_GraphPara; //定义一个管理图形参数的对象 • 为了在各个图形元素类以及一些对话框类中使用这个图形参数对象m_GraphPara,可定义一个全局的CGraphPara指针,并把这个指针指向当前文档对象中的CGraphPara对象m_GraphPara。在drawdoc.cpp中定义一个全局的CGraphPara指针(所谓全局定义,就是把变量定义在所有函数的外面)。 CGraphPara *p_GraphPara;

  43. 为了把这个指针指向当前文档对象中的CGraphPara对象m_GraphPara,在文档类CDrawDoc的构造函数中加入如下代码:为了把这个指针指向当前文档对象中的CGraphPara对象m_GraphPara,在文档类CDrawDoc的构造函数中加入如下代码: CDrawDoc::CDrawDoc() { p_GraphPara=&m_GraphPara; //将公用的GraphPara类的指针指向当前文档的GraphPara对象 } • 如果要在其他别的实现文件中使用这个对象指针,只需要在其他文件中加入这个全局指针的外部引用: extern CGraphPara *p_GraphPara;

  44. (3)实现文档的管理功能 • 增加图形元素 • 在应用程序Draw中增加一个图形元素对象时,需要进行以下两个步骤的操作: ①需要创建一个图形元素对象,并用图形元素的实际数据初始化这个图形元素对象。如增加一条直线时,需要创建一个CLine对象,并用这条直线的实际数据(起始点、所在图层、颜色等)初始化这个CLine对象的成员变量。 ②需要把直线新创建的图形元素对象的指针,增加到文档类管理图形元素对象指针的对象中。如增加一条CLine对象后,需要把指向这个Cline对象的指针增加到文档类的m_LineArray对象中。

  45. 为了实现增加各类图形元素的功能,在文档类CDrawDoc中定义几个函数,分别来完成增加各类图形元素的操作功能。在CDrawDoc中定义几个函数,分别完成增加各类图形元素的操作功能。为了实现增加各类图形元素的功能,在文档类CDrawDoc中定义几个函数,分别来完成增加各类图形元素的操作功能。在CDrawDoc中定义几个函数,分别完成增加各类图形元素的操作功能。 CLine* AddLine(short ColorPen,short ColorBrush,short LineWide,short LineType,short Layer,int id_only,float X1,float Y1, float X2,float Y2); //增加一条直线 CPline* AddPLine(short ColorPen,short ColorBrush, short LineWide,short LineType,short Layer,int id_only,int Numble, PointStruct* PointList,BOOL b_Fill);

  46. CCircle* AddCircle(short ColorPen,short ColorBrush, short LineWide,short LineType,short Layer,int id_only, float CircleX,float CircleY,float CircleR,BOOL Fill); CArc* AddArc(short ColorPen,short ColorBrush,short LineWide,short LineType,short Layer,int id_only,float CircleX, float CircleY,float CircleR,BOOL Fill,float Angle1,float Angle2); CText* AddText(short ColorPen,short ColorBrush,short LineWide,short LineType,short Layer,int id_only,float StartX, float StartY,float Angle1, float Angle2,float TextHeight,float TextWide, float OffWide,unsigned char TextFont,int TextLong,CString);

  47. 这五个函数分别用来实现增加一条直线、一条连续直线或封闭多边形区域、一个圆或圆区域、一个圆弧、一个标注文本的功能。函数返回指向新图形元素的指针。在Drawdoc.cpp中加入这五个函数的实现代码。这五个函数分别用来实现增加一条直线、一条连续直线或封闭多边形区域、一个圆或圆区域、一个圆弧、一个标注文本的功能。函数返回指向新图形元素的指针。在Drawdoc.cpp中加入这五个函数的实现代码。

  48. CLine* CDrawDoc::AddLine(short ColorPen,short ColorBrush,short LineWide,short LineType,short Layer,int id_only,float X1,float Y1,float X2,float Y2) { //动态创建并初始化一个CLine对象 CLine* p_Line=new CLine(ColorPen,ColorBrush,LineWide, LineType,Layer,id_only,0,X1,Y1,X2,Y2); //将指向新建CLine对象的指针增加到m_LineArray对象中 m_LineArray.Add(p_Line); //返回指向新增CLine对象的指针 return p_Line; }

  49. CPline* CDrawDoc::AddPLine(short ColorPen,short ColorBrush,short LineWide,short LineType,short Layer,int id_only,int Numble,PointStruct* PointList,BOOL Fill) { CPline* p_Pline=new CPline(ColorPen,ColorBrush,LineWide, LineType,Layer,id_only,0,Numble,PointList,Fill); m_PLineArray.Add(p_Pline); return p_Pline; }

More Related