1、第10章 图 形 设 计,10.1 绘图概述 10.2 绘图的基本步骤 10.3 绘制图形 10.4 创建画图工具 10.5 绘制文本,10.1 绘图概述10.1.1 绘图的基本知识(1)像素 (2)坐标系,(3)Paint事件这种在屏幕上进行绘制的操作称为“绘画”。窗体和控件都有一个Paint事件。每当需要重新绘制窗体和控件(例如,首次显示窗体或窗体由另一个窗口覆盖)时就会发生该事件。用户所编写的用于显示图形的任何代码通常都包含在Paint事件处理程序中。,(4)颜色颜色是绘图功能中非常重要的一部分,在C#中颜色用Color结构和Color列举来表示。在Color结构中颜色由4个整数值Red
2、、Green、Blue和Alpha表示。其中Red、Green和Blue可简写成R、G、B,表示颜色的红、绿、蓝三原色;Alpha表示不透明度。可以通过Color类的FromArgb方法来设置和获取颜色。FromArgb方法使用的语法格式如下:Color.FromArgb(A,R,G,B),10.1.2 什么是GDI+GDI+是Windows的Graphics Device Interface(图形设备接口)。GDI+是一个2D(二维)图形库,通过它可以创建图形、绘制文本以及将图形图像作为对象来操作。,10.1.3 Graphics类Graphics类封装一个GDI+绘图图面,无法继承此类。该
3、类提供了对象绘制到显示设备的方法,且与特定的设备上下文关联。也就是说,Graphics类是GDI+的核心类,它包含许多绘制操作方法和图像操作方法,所有C#的图形绘制都是通过它提供的方法进行的。例如,DrawLine方法就是绘制一条连接由坐标对指定的两个点的线条。,10.2 绘图的基本步骤1. 创建Graphics对象在绘图之前,必须在指定的窗体上创建一个Graphics对象,即建立一块画布,只有创建了Graphics对象,才可以调用Graphics类的方法画图。但是,不能直接建立Graphics类的对象,例如,以下语句是错误的:Graphics 对象名= new Graphics();,(1)
4、调用窗体CreateGraphics方法来建立Graphics对象通过当前窗体的CreateGraphics方法,把当前窗体的画笔、字体和颜色作为默认值,获取对Grpahics对象的引用。例如,在窗体Form1的Paint事件(该事件是在绘制窗体时发生)中编写如下代码:private void Form1_Paint(object sender, PaintEventArgs e) Graphics gobj = this.CreateGraphics();/调用gobj的方法画图,(2)在窗体的Paint事件处理过程中建立Graphics对象在窗体的Paint事件处理过程中,通过Graphi
5、cs属性获取Graphics对象。例如,在窗体Form1的Paint事件中编写如下代码:private void Form1_Paint(object sender, PaintEventArgs e) Graphics gobj = e.Graphics;/调用gobj的方法画图,2. 创建绘图工具创建Graphics对象后,可用于绘制线条和形状、呈现文本或显示与操作图像。与Graphics对象一起使用的主要对象有以下几类。(1)Pen类:用于绘制线条、勾勒形状轮廓或呈现其他几何表示形式。(2)Brush类:用于填充图形区域,如实心形状、图像或文本。(3)Font类:提供有关在呈现文本时的字
6、体。(4)Color结构:表示要显示的不同颜色。,3. 使用Graphics类提供的方法绘图Graphics类提供的绘图方法可以绘制空心图形、填充图形和文本等:绘制空心图形的方法:DrawArc、DrawBezier、DrawEllipse、 Drawlmage、DrawLine、DrawPolygon和DrawRectangle等。绘制填充图形的方法:FillClosedCurve、FillEllipse、FillPath、 FillPolygon和FillRectangle等。绘制文字的方法:Drawstring。,4. 清理Graphics对象当在Graphics对象上绘图完成后,有时需
7、要重新绘制新的图形,这时需要清理画布对象。其使用方法为:画布对象.Clear(颜色);其功能是将画布对象的内容清理成指定的颜色。例如,以下语句将画布对象gobj清理为白色:gobj.Clear(Color.White);,5. 释放资源对于在程序中创建的Graphics、Pen、Brush等资源对象,在不再使用时应尽快释放,调用该对象的Dispose方法即可。如果不调用Dispose方法,则系统将自动回收这些资源,但释放资源的时间会滞后。,【例10.1】 设计一个窗体,画出4条线构成一个矩形 。,Form1窗体 事件过程: private void Form1_Paint(object sen
8、der, PaintEventArgs e) Graphics gobj = this.CreateGraphics();int x, y, w, h;x = 10; y = 10; w = 150; h = 100;gobj.DrawLine(Pens.Blue, x, y, x + w, y);gobj.DrawLine(Pens.Blue, x, y, x, y + h);gobj.DrawLine(Pens.Blue, x + w, y, x + w, y + h);gobj.DrawLine(Pens.Blue, x, y + h, x + w, y + h); ,10.3 绘制图形
9、,10.3.1 绘制直线Graphics.DrawLine(Pen, 起点坐标, 终点坐标);绘制直线时需指明直线的起点坐标(即起点列、行坐标)和终点坐标(即终点列、行坐标)。Pen是画笔对象。,10.3.2 绘制矩形 矩形有空心图形和填充图形之分。 1. 绘制空心矩形Graphics.DrawRectangle(Pen, Rectangle);Graphics.DrawRectangles(Pen, Rectangle);其中,DrawPolygon方法绘制由一个Rectangle结构定义的多边形,而DrawRectangles方法绘制一系列由Rectangle结构指定的矩形。 2. 绘制填
10、充矩形Graphics.FillRectangle(Brush, Rectangle);Graphics.FillRectangles(Brush, Rectangle); 其中,FillRectangle方法填充由Rectangle指定的矩形的内部。FillRectangles方法填充由 Rectangle 结构指定的一组矩形的内部。Brush是画刷对象。,【例10.2】 设计一个窗体,说明矩形方法的使用。,Form2,事件过程: private void Form2_Paint(object sender, PaintEventArgs e) Graphics gobj=this.Crea
11、teGraphics();Rectangle rec1=new Rectangle(20, 20, 50, 50); /定义一个矩形rec1Rectangle rec2=new Rectangle(80, 20, 80, 100); /定义一个矩形rec2gobj.DrawRectangle(Pens.Blue, rec1); /绘制一个空心矩形gobj.FillRectangle(Brushes.Red, rec2); /绘制一个填充矩形 ,10.3.3 绘制多边形多边形分为空心图形和填充图形。 1. 绘制空心多边形Graphics.DrawPolygon(Pen, Point);其中Poi
12、nt数组是由一组Point结构对象定义的多边形。Pen对象指出画线的画笔。 2. 绘制填充多边形Graphics.FillPolygon(Brush, Point);,【例10.3】 设计一个窗体,说明多边形方法的使用。,Form3,事件过程: private void Form3_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();Point parray1 = new Point(20, 20), /定义点数组parray1new Point(20, 80),new Point(100, 80
13、);gobj.DrawPolygon(Pens.Blue, parray1);Point parray2= new Point(150, 10), new Point(120, 50),new Point(150, 90), new Point(200, 90), /定义点数组parray2new Point(230, 50), new Point(200, 10);gobj.FillPolygon(Brushes.Red, parray2); ,10.3.4 绘制圆和椭圆 圆和椭圆有空心图形和填充图形之分。 1. 绘制空心圆和椭圆Graphics.DrawEllipse(Pen, Recta
14、ngle);绘制圆和椭圆的方法相同,当宽和高的取值相同时,椭圆就变成圆了。 2. 绘制填充圆和椭圆Graphics.FillEllipse(Brush, Rectangle);,【例10.4】 设计一个窗体,说明圆和椭圆方法的使用。,Form4,事件过程: private void Form4_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();gobj.DrawEllipse(Pens.Red, 20, 20, 150, 100);gobj.DrawEllipse(Pens.Blue, 50,
15、40, 60, 60);gobj.FillEllipse(Brushes.Green, 180, 40, 100, 60); ,10.3.5 绘制弧线Graphics.DrawArc (Pen,起点坐标,终点坐标,起始角度,仰角参数);其中最后两个参数是弧线的起始角度和仰角参数。,【例10.5】 设计一个窗体,说明弧线方法的使用。,Form5,事件过程:private void Form5_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();gobj.DrawArc(Pens.Red, 30, 3
16、0, 140, 70, 30, 180);gobj.DrawArc(Pens.Black, 50, 40, 140, 70, 60, 270); ,10.3.6 绘制饼形 饼形有空心图形和填充图形之分。 1. 绘制空心饼形Graphics.DrawPie(Pen, Rectangle, 起始角度, 仰角参数);其中,若“仰角参数”大于360或小于-360,则将其分别视为360或-360。 2. 绘制填充饼形Graphics.FillPie(Brush, Rectangle, 起始角度, 仰角参数);,【例10.6】 设计一个窗体,说明饼形方法的使用。,Form6,事件过程: private v
17、oid Form6_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();Rectangle rec1=new Rectangle(20, 20, 100, 70);Rectangle rec2=new Rectangle(130, 30, 140, 70);gobj.DrawPie(Pens.Red, rec1, 20, 180);gobj.FillPie(Brushes.Blue, rec2, 30, 180); ,10.3.7 绘制非闭合曲线Graphics.DrawCurve(Pen,Poi
18、nt,offset,numberofsegments,tension);其中,Point为点数组,必须包含至少4个点。offset从Point参数数组中的第一个元素到曲线中起始点的偏移量,如果从第一个点开始画,则偏移量为0,如果从第二个点开始画,则偏移量为1,以此类推。 numberOfSegments表示起始点之后要包含在曲线中的段数。tension表示该值指定曲线的张力,大于或等于0.0F的值,用来指定曲线的拉紧程度,值越大,拉紧程度越大,当值为0时,则此方法绘制直线段以连接这些点。,【例10.7】 设计一个窗体,说明非闭合曲线方法的使用。,Form7,事件过程: private void
19、 Form7_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();Point parray = new Point(30, 30), new Point(50, 50),new Point(80, 90), new Point(70, 60),new Point(130, 50), new Point(150, 10);gobj.DrawCurve(Pens.Red, parray, 0, 5, 0.2f); ,10.3.8 绘制闭合曲线 闭合曲线有空心图形和填充图形之分。 1. 绘制空心闭合曲线
20、Graphics.DrawClosedCurve(Pen, Point);Point表示点的数组,其中必须包含至少4个点。,2. 绘制填充闭合曲线Graphics.FillClosedCurve(Brush, point);,【例10.8】 设计一个窗体,说明闭合曲线方法的使用。,Form8,事件过程: private void Form8_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();Point parray1 = new Point(20, 20), new Point(50, 50),
21、new Point(80, 90), new Point(70, 60),new Point(110, 50), new Point(100, 10);Point parray2 = new Point(140, 20), new Point(170, 50),new Point(200, 90), new Point(190, 60),new Point(230, 50), new Point(220, 10);gobj.DrawClosedCurve(Pens.Red, parray1);gobj.FillClosedCurve(Brushes.Blue, parray2); ,10.3.
22、9 绘制贝济埃曲线Bezier Curve贝济埃曲线是一种用数学方法生成的能显示非一致曲线的线。Graphics.DrawBezier(Pen, point1, point2, point3, point4);其中,point1、point2p、point3和point4为4个Point结构或者PointF结构对象,分别表示曲线的起始点、第1个控制点、第2个控制点和曲线的结束点。,【例10.9】 设计一个窗体,说明贝济埃曲线方法的使用。,Form9,事件过程: private void Form9_Paint(object sender, PaintEventArgs e) Graphics
23、gobj=this.CreateGraphics();Point p1 = new Point(30, 30);Point p2 = new Point(50, 50);Point p3 = new Point(80, 90);Point p4 = new Point(130, 30);gobj.DrawBezier(Pens.Red, p1, p2, p3, p4); ,10.4 创建画图工具画图工具包括画笔、笔刷、字体和颜色等。 10.4.1 创建画笔画笔是用来画线的基本对象,同时通过画笔在窗体上绘制各种颜色的图形。在绘图之前首先需要创建一个画笔,语法格式如下:Pen 画笔名称;画笔名称
24、= new Pen(颜色, 宽度);或Pen 画笔名称 = new Pen(颜色, 宽度);,【例10.10】 设计一个窗体,说明画笔的使用方法。,Form10,不放置任何控件,在其上设计如下事件过程: private void Form10_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics(); /创建Graphics对象Pen redPen = new Pen(Color.Red); /创建Pen对象redPenPen bluePen = new Pen(Color.Blue, 8); /创建P
25、en对象bluePenPen greenPen = new Pen(Color.Green, 3); /创建Pen对象greenPenPoint p1 = new Point(40, 30);Point p2 = new Point(150, 30);redPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; /设置直线样式为虚线,redPen.Width = 5; /设置直线宽度gobj.DrawLine(redPen, 20, 20, 20, 150);bluePen.StartCap =System.Drawing.Drawin
26、g2D.LineCap.RoundAnchor; /设置直线起点样式bluePen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; /设置直线终点样式gobj.DrawLine(bluePen, p1, p2);gobj.DrawLine(greenPen, 40, 50, 150, 150); ,10.4.2 创建笔刷GDI+提供了几种不同形式的画刷,如实心笔刷(SolidBrush )、纹理笔刷(TextureBrush )、阴影笔刷(HatchBrush )和渐变笔刷(LinearGradientBrush )等。 1. 实心
27、笔刷SolidBrush 笔刷名称 = new SolidBrush(笔刷颜色);例如定义一个颜色为红色的实心笔刷:SolidBrush redBrush = new SolidBrush(Color.Red); 2. 阴影笔刷HatchBrush笔刷是一种复杂的画刷,它通过绘制一种样式来填充区域,作用是在某一种图案来填充图形,创建方法如下:HatchBrush 笔刷名称 = new HatchBrush(HatchStyle, _ForegroundColor,BackgroundColor);,指出HatchBrush对象的阴影样式,【例10.11】 设计一个窗体,说明画笔的使用方法。,F
28、orm11,事件过程: private void Form11_Paint(object sender, PaintEventArgs e) Graphics gobj=this.CreateGraphics();SolidBrush myBrush1 = new SolidBrush(Color.Red); /声明实心画笔HatchBrush myBrush2 = new HatchBrush(HatchStyle.Vertical, Color.Blue, Color.Green);Pen blackPen = new Pen(Color.Black, 3);gobj.FillRectan
29、gle(myBrush1, 20, 20, 100, 100); /绘制并填充矩形gobj.DrawRectangle(blackPen, 20, 20, 100, 100);/绘制绿色背景色蓝色垂直阴影线矩形gobj.FillRectangle(myBrush2, 150, 20, 100, 100); ,10.4.3 创建字体Font类定义了文字的格式,如字体、大小和样式等。创建字体对象的一般语法格式如下:Font 字体对象 = new Font(字体名称,字体大小, 字体样式);其中,“字体样式”为FontStyle枚举类型,其取值及说明如表10.4所示。例如,以下语句创建一个字体为“宋
30、体”,大小为20,样式为粗体的Font对象f:Font f = new Font(“宋体“, 20, FontStyle.Bold);,10.5 绘制文本,Graphics对象提供了文字设置的DrawString方法:Graphics.DrawString (字符串,Font,Brush,Point,字体格式);Graphics.DrawString (字符串,Font,Brush,Rectangle,字体格式); 其中,各参数的说明如下:(1)“字符串”指出要绘制的字符串,也就是要输出的文本。(2)Font为创建的字体对象,用来指出字符串的文本格式。(3)Brush为创建的笔刷对象,它确定所
31、绘制文本的颜色和纹理。(4)Point表示为Point结构或者为PointF结构的点,这个点表示绘制文本的起始位置,它指定所绘制文本的左上角。Rectangle表示由Rectangle结构指定的矩形,矩形左上角的坐标为文本的起始位置,文本在矩形的范围内输出。(5)“字体格式”是一个StringFormat对象,用于指定应用于所绘制文本的格式化属性,如行距和对齐方式等。,【例10.12】 设计一个窗体,说明绘制文字的使用方法。,Form12,事件过程: private void Form12_Paint(object sender, PaintEventArgs e) Graphics gobj
32、=this.CreateGraphics();StringFormat sf1 = new StringFormat();StringFormat sf2 = new StringFormat();Font f = new Font(“隶书“, 20, FontStyle.Bold);HatchBrush bobj1 = new HatchBrush(HatchStyle.Vertical,Color.Blue, Color.Green);SolidBrush bobj2 = new SolidBrush(Color.Red);sf1.Alignment = StringAlignment.Far;sf2.FormatFlags = StringFormatFlags.DirectionVertical;gobj.DrawString(“中华人民共和国“, f, bobj1, 220, 15, sf1);gobj.DrawString(“北京奥运会“, f, bobj2, 100, 50, sf2); ,