第十章 图形处理 本章学习目标: 通过本章的学习,读者能够灵活运用GDI+提供的功能绘制自定义图形和实现简单的动画效果。 本章学习要点: 第十章 图形处理 本章学习目标: 通过本章的学习,读者能够灵活运用GDI+提供的功能绘制自定义图形和实现简单的动画效果。 本章学习要点: (1)创建Graphics对象,使用GDI+绘图。 (2)使用画笔和填充工具,学习描述对象的颜色和透明度的Color结构绘制各种图形。 (3)使用排版功能进行文本处理。 (4)使用图像功能进行翻转、缩放、剪切等图像处理。 (5)简单动画设计的编程。
第十章 图形处理 在应用程序中加入图形、图像,会使我们的程序界面更加漂亮、友好。VB.NET的GDI (Graphics Device Interface图形设备接口)提供了强大的绘图功能,是微软公司为程序员提供的针对Windows平台的新一代二维图形系统。它的完全面向对象的特征和优良设计在保证高效率的同时,也为程序员绘制各种各样的图形和显示图像提供了简单易用的接口。
10.1 绘图的基础知识 10.1.1 GDI+概述 GDI+是对“图形设备接口(GDI)”的一个扩展,是一套特殊的“应用程序编程接口(API)”。它所提供的类可用于创建二维矢量图形(“矢量”是创建图形的一种高性能技术)、操纵字体以及插入图像。GDI+在扩展GDI 的同时,还简化了编程模型并添加了一些新特性,比如图形路径、扩展的图像文件支持以及alpha 混合等等。使用GDI+API,程序员可以灵活地创建图像,不必关心图形硬件和运行平台的细节。
10.1 绘图的基础知识 GDI+在System.Drawing.Dll程序集中定义,它的相关类都分布在以下命令空间。 System.Drawing:提供了对 GDI+ 基本图形功能的访问。 System.Drawing2D:提供高级的二维和矢量图形功能。 System Imaging :提供高级 GDI+ 图像处理功能。 System.Drawing.Text:允许用户创建和使用多种字体。
10.1 绘图的基础知识 10.1.2 GDI+的坐标系统 要在VB.NET中绘图,首先需要理解GDI+的坐标系统(图10.1),所谓“坐标系统”是对屏幕上的每个点进行标识的一种方案。GUI组件(比如Panel 或Form )左上角的坐标默认为(0 , 0),一对坐标同时含有x坐标(水平坐标)和y坐标(垂直坐标)。x 坐标是距离左上角的水平距离(朝右),y 坐标是距离左上角的垂直距离(向下)。我们要指定( x , y)坐标,以便将文本和图形定位在屏幕上。坐标单位是像素( 图形元素),即显示器能分辨的最小单元。不同显示器可能采用不同分辫率,所以像素在这些显示器上的密度是不同的,这可能导致图形大小在不同显示器上有所区别。用户通常在一定程度上可以配置单独一台显示器上显示的像素数量。
10.1 绘图的基础知识 图10.1 GDI坐标系统及像素点
10.2 用GDI+绘图 Graphics类封装了GDI+的绘图画板,是GDI+绘图的核心类。需要首先创建Graphics对象,然后才可以使用GDI+绘制线条和形状、呈现文本或显示与操作图像。处理图形包括以下两个步骤: (1)创建Graphics对象。 (2)使用Graphics 对象绘制线条和形状、呈现文本或显示与操作图像。 10.2.1 创建Graphics 对象 Graphics 类提供将对象绘制到显示设备的方法,它与特定的设备上下文关联。
10.2 用GDI+绘图 1.Paint 事件处理程序中的PaintEventArgs 在窗体或控件的 Paint 事件中接收对图形对象的引用,作为 PaintEventArgs 的一部分。 在为控件创建绘制代码时,通常会使用此方法来获取对图形对象的引用。要获取对Paint事件的PaintEventArgs中Graphics对象的引用 ,需要完成以下步骤: (1) 声明Graphics对象。 (2) 分配变量来引用作为PaintEventArgs的一部分传递的Graphics 对象。 (3) 插入代码来绘制窗体或控件。
10.2 用GDI+绘图 例10-1:演示如何从Paint事件中的PaintEventArgs引用 Graphics 对象。 Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Froms.paintEventArgs) Handles MyBase.Paint Dim g As Graphics=e.Graphics ‘声明Graphics对象g并将其设置应用在PaintEventArgs内的Graphics对象 ‘在此插入代码描绘窗体 End Sub 现在就可以用变量g 在窗体上描绘形状和文本字符串了。
10.2 用GDI+绘图 2.CreateGraphics 方法 通过调用从 System.Windows.Forms.Control 继承的对象的 Control.CreateGraphics 方法来实现。调用某控件或窗体的CreateGraphics方法来获取对Graphics 对象的引用,该对象表示该控件或窗体的绘图表面。如果想在已存在的窗体或控件上绘图,则可使用此方法。 例如: Dim g as Graphics ‘设置g为一个图形对象,其表示绘制控件的 表面或窗体g为图形对象的一个成员 g=Me.CreateGraphics
10.2 用GDI+绘图 3.从Image 对象创建 从继承来自“图像”的任何对象创建Graphics 对象,此方法在用户需要更改已存在的图像时十分有用。可以从Image类派生的任何对象创建Graphics对象,为此需要调用Graphics.FormImage方法,并提供要从其中创建Graphics对象的Image变量的名称。 例10-2 :演示了如何使用Bitmap对象,代码如下: Dim myBitmap as New Bitmap("C:\mypic.bmp") Dim g as Graphics=Graphics.FromImage(myBitmap) 注意:只能从非索引 .bmp 文件(如 16 位、24 位和 32 位的 .bmp 文件)创建 Graphics 对象。索引 .bmp 文件的像素将索引保存到颜色表中,而非索引 .bmp 文件的每个像素保存的是颜色值。
10.2 用GDI+绘图 10.2.2 绘制和操作图形 Graphics 对象在创建后,可用于绘制线条和形状、呈现文本或显示与操作图像。与Graphics对象一起使用的用户对象有以下几种: (1) Pen类:用于绘制线条、勾勒形状轮廓或呈现其他几何表示形式。 (2) Brush类:用指定的颜色、样式、纹理来填充封闭的图形。 (3) Font 类:提供有关在显示文本时要使用的样式说明。 (4) Color结构:用来描述对象的颜色和透明度。
10.2 用GDI+绘图 用GDI+绘制图形,先获取图形对象的引用,然后创建Pen用于轮廓的描绘或Brush用于封闭图形的填充,然后再绘制各种形状的图形。 1.创建Graphics 对象 例如VB.NET包含一个对Buttonl图形对象的引用,则可定义如下: Dim g as Graphics=Buttonl.CreateGraphics 2.用Pen绘制图形 Pen 对象存储要绘制项的颜色、宽度和线型属性,将 Pen 对象作为参数之一传递给绘制方法。
10.2 用GDI+绘图 例如,下面的示例演示 DrawRectangle 方法的一个变体接收一个 Pen 对象和四个整数,并绘制一个宽 100、高 50 且左上角位于 (20, 10) 的矩形: myGraphics.DrawRectangle (myPen, 20, 10, 100, 50) 例如,创建用于绘制线条的Pen 类的实例,设置所有相应的属性。 (1) Dim myPen as Pen=new Pen (Color.Red ) ‘用指定的颜色画线 (2) Dim myPen as Pen=new Pen (Color.Red , Width ) myPen.Width=5 ‘用指定的颜色和宽度画线
10.2 用GDI+绘图 (3) Dim myPen as Pen=new Pen (Color.Red ) myPen.DashStyle= 枚举值 ‘用指定样式画线 其中枚举值定义了画线的样式,各个枚举值如下所示: Custom:指定用户自定义的画线样式 Dash:指定由线段组成的直线 DashDot:指定由重复的点线图案构成的直线 DashDotDot:指定由重复的点点线图案构成的直线 Dot:指定由点构成的直线 Solid:指定实线 例如:Dim myPen As Pen = New Pen(Color.ForestGreen, 4.0F) myPen.DashStyle = Drawing2D.DashStyle.DashDotDot
10.2 用GDI+绘图 3.用brush填充图形 Pen对象定义了封闭图形的轮廓线的属性,而图形内部属性可以用Brush类来定义。GDI+提供了几个笔刷来填充内部轮廓,几种填充形式都是Brush类的派生类。 (1) 用单色填充图形 SolidBrush类是一个单色填充类,其功能是用一种颜色填充图形,因此该类只有一种属性,即Color(颜色)属性。创建一个SolidBrush 对象,然后将SolidBrush对象传送给图形对象中的一个填充方法的参数。 例10-3:用红色填充一个椭圆,代码如下。 Dim g As Graphics = Me.CreateGraphics Dim solidBrush As New SolidBrush(Color.FromArgb(50, Color.Red)) g.FillEllipse(solidBrush, 0, 0, 100, 60) 在代码中,Color.FromArgb方法指定颜色,第1个参数50表示透明度,第二个参数表示填充颜色为红色。椭圆的外接矩形用(0,0,100,60)指定。
10.2 用GDI+绘图 (2) 用hatch模式填充图形 HatchBruh类是用阴影样式、前景色和背景色填充,有 54 种不同的阴影样式,前景色定义线条的颜色,背景色定义各线条之间间隙的颜色,格式如下: HatchBrush (HatchStyle, Color) 使用指定的 HatchStyle 枚举和前景色填充 HatchBrush (HatchStyle, Color,Color)使用指定的 HatchStyle 枚举、前景和 背景色填充 背景色:绘制的阴影线条之间的空间的颜色 前景色:绘制的阴影线条的颜色 填充样式:绘制的阴影样式 Hatchstyle参数可以是Hatchstyle 枚举类型的任何值。在枚举类型中有50多个元素,例如: Horizontal 水平线的图案 Cross 交叉的水平线和垂直线 Vertical 垂直线的图案 DashedHorizontal 虚线水平线等等
10.2 用GDI+绘图 例10-4:用hatch 模式填充一个椭圆,代码如下: Dim hBrush As New HatchBrush(HatchStyle.Horizontal, Color.Red, Color.FromArgb(255, 128, 255, 255) ) e.Graphics.FillEllipse(hBrush, 0, 0, 100, 60) 运行结果如图10.2 所示。 图10.2 用hatch填充图形
10.2 用GDI+绘图 (3) 用图像填充图形 TextureBrush 类的功能是用一个图像填充图形,该类需要一个图像对象作参考,用Image和TextureBrush 类填充一个封闭的图形。格式如下: TextureBrush (Image) 用指定的图像更新 TextureBrush 对象 TextureBrush (Image, Rectangle) 用指定的图像和边框填充 TextureBrush (Image, WrapMode) 用指定的图像和自动换行模式填充 TextureBrush (Image, Rectangle, ImageAttributes) 用指定图像、边框和图像属性填充 TextureBrush (Image, WrapMode, Rectangle) 用指定图像、自动换行模式和边框填充 参数说明如下: WrapMode:指定图像填充区域时的平铺方式,枚举值如下: Clamp 没有平铺 Tile 平铺图像 TileFlipX 水平反转图像,然后平铺该图像 TileFlipXY 水平和垂直反转图像,然后平铺该图像 TileFlipY 垂直反转图像,然后平铺该图像
10.2 用GDI+绘图 例10-5:用一个图像平铺并渐变填充一个椭圆,代码如下: Dim formGraphics As Graphics = Me.CreateGraphics() Dim image1 = New Bitmap("c:\picture.bmp") Dim texture As New TextureBrush(image1) texture.WrapMode = Drawing2D.WrapMode.Tile formGraphics.FillEllipse(texture, New Rectangle(0, 0, 400, 400)) 其中:WrapMode的枚举类型存在于Drawing2D命名空间中。 例10-6:下面的示例说明不同类型的平铺效果。用如图10.3所示的75 x 75样图平铺一个200x200 的矩形。 图10.3 基本图形
10.2 用GDI+绘图 若将平铺模式设为: tBrush.WrapMode=WrapMode.TileFlipX Dim image = New Bitmap("c:\picture.bmp") Dim tBrush As New TextureBrush(image) tBrush.WrapMode = Drawing2D.WrapMode.Tile Dim blackPen As New Pen(Color.Black) e.Graphics.FillRectangle(tBrush, New Rectangle(0,0,200,200)) e.Graphics.DrawRectangle(blackPen,NewRectangle(0,0,200,200)) 若将平铺模式设为: tBrush.WrapMode=WrapMode.TileFlipX tBrush.WrapMode=WrapMode.TileFlipY tBrush.WrapMode=WrapMode.TileFlipXY, 则运行效果分别为图10.4、图10.5、 10.6、 10.7所示。
图10.4填充图形 图10.5 水平反转 图10.6垂直反转 图10.7水平垂直反转
10.2 用GDI+绘图 (4) 用直线形颜色渐变填充图形 (4) 用直线形颜色渐变填充图形 利用直线形颜色渐变改变色彩,GDI+提供了水平、垂直、对角直线形渐变样式。所有渐变都是沿由矩形的宽度或两个点指定的直线定义的。默认情况下,双色渐变是沿指定直线从起始色到结束色的均匀水平线性混合。具体格式如下: LinearGradientBrush (Point, Point, Color1, Color2) 使用指定的点和颜色渐变填充 LinearGradientBrush(Rectangle,Color1,Color2, LinearGradientMode) 根据矩形、起始颜色和结束颜色以及方向渐变填充 LinearGradientBrush (Rectangle, Color1, Color2, angle) 根据矩形、起始颜色和结束颜色以及方向角度渐变填充
10.2 用GDI+绘图 其中参数含义为: linearGradientMode 指定渐变方向,渐变方向决定渐变的起点和终点。取值为: Rectangle 指定线性渐变的界限 Color1 表示渐变起始色 Color2 表示渐变结束色 angle 渐变方向线的角度(从 X 轴以顺时针角度计算) linearGradientMode 指定渐变方向,渐变方向决定渐变的起点和终点。取值为: BackwardDiagonal 指定从右上到左下的渐变 ForwardDiagonal 指定从左上到右下的渐变 Horizontal 指定从左到右的渐变 Vertical 指定从上到下的渐变 例10-7:用渐变填充图形。
10.2 用GDI+绘图 设想一个矩形。左边缘是黑色(0,0,0) ,右边缘是红色(255,0,0)。如果该矩形宽256 像素,右边的红色像素比左边多。最左边的像素为(0,0,0 ) , 下一个为(l,0,0 ) ,第3 个为(2,0,0),依次类推,直到到达最右边,色彩成分为(255,0,0 ),这些被插入的色彩值构成了渐变变化的颜色。 例10-8:用直线渐变填充一条直线、一个椭圆和一个矩形,代码如下: ‘将不透明的红色和蓝色分别作为第3 和第4 个参数传递 Dim linGrBrush As New LinearGradientBrush(New Point(0, 10), NewPoint(200, 10),Color.FromArgb(255, 255, 0, 0), Color.FromArgb(255, 0, 0, 255)) Dim pen As New Pen(linGrBrush) e.Graphics.DrawLine(pen, 0, 10, 200, 10) e.Graphics.FillEllipse(linGrBrush, 0, 30, 200, 100) e.Graphics.FillRectangle(linGrBrush, 0, 155, 500, 30)
10.2 用GDI+绘图 10.8 用直线渐变填充图形 在上例中,有如下几点说明: ① 在LinearGradientBrush 构造函数中, 水平直线从(0,10)绘制到(200,10),其颜色从红色渐变为蓝色。 ② 椭圆和矩形的水平坐标从0变到200时颜色由红色渐变为蓝色。 ③ 当水平坐标值超过200 时,颜色梯度重复变化。 用直线渐变填充图形的结果如图10.8 所示: 10.8 用直线渐变填充图形
10.2 用GDI+绘图 (5) 用路径颜色渐变填充图形 pathGradientBrush类可以为一个路径的中部指定一种颜色,为路径的边缘指定另一种颜色,也可以为沿路径的边缘几个点中的每一个点分别指定颜色。在GDI+中,一个路径是一系列直线和由Graphics 对象维持的曲线组成。 例10-9 :利用在边界上指定的点来填充。由星形轨迹构造路径渐变画笔,将星形中心的颜色设置为红色,然后在 points 数组中的各个点处指定不同的颜色(存储在 colors 数组中)。最后一条语句用路径渐变画笔填充星形轨迹在边缘指定的点,代码如下:运行结果如图10.9 所示。
10.2 用GDI+绘图 Dim points As Point ( ) = {_ '在一个数组中放置多边形的点 New Point( 75, 0), New Point(100, 50),_ New Point(150, 50), New Point(112, 75),_ New Point(150,150), New Point( 75,100),_ New Point( 0,150), New Point( 37, 75),_ New Point( 0, 50), New Point(50, 50) } Dim path As New GraphicsPath() '用点阵构造一个路径 Path.AddLines (points) ‘向此 GraphicsPath末尾追加一系列相互连接的线段 Dim pthGrBrush As New PathGradientBrush(path) '用路径构造一个路径渐变 pthGrBrush.CenterColor =Color. FromArgb(255,255,0,0) ‘路径的中部设颜色为红色 Dim colors As Color() = {_ '设置数组中点的颜色 Color.FromArgb(255,0,0,0), Color.FromArgb(255,0,255,0),_ Color.FromArgb(255,0,0,255), Color.FromArgb(255,255,255,255), _ Color.FromArgb(255,0,0,0), Color.FromArgb(255,0,255,0),_ Color.FromArgb(255,0,0,255), Color.FromArgb(255,255,255,255),_ Color.FromArgb(255,0,0,0),Color.FromArgb(255,0,255,0) }
10.2 用GDI+绘图 pthGrBrush. SurroundColors = colors ’获取与填充的路径中的点相对应的颜色的数组 e.Graphics. FillPath(pthGrBrush, path) '填充路径 图10.9构造路径填充图形
10.3 颜色控制 在GDI+中用Color 结构定义处理颜色的方法和常量,颜色是一个32 位的值,由红色、绿色、蓝色及通道组成。每种颜色及通道各占8 位,取值范围是0~255 之间的整数值,这些值结合起来可以定义某种具体的颜色。通道代表颜色的透明度,即颜色被背景色混合的程度。颜色的RGB 值和背景色的RGB值产生一种加权混合效果,其取值在0~255 之间变化,O 代表全透明,255 代表全不透明。通道混合是背景色和源色一个像素一个像素地混合,源色中的3 个元素(红色、绿色和监色)各自根据下面的公式和背景色中相应元素混合。 显示色=源色 × alpha/255 +背景色×(255 - alpha ) / 255 例如,假定源色中的红色成分是150 ,背景色中的红色成分是100,如果通道值是200, 那么结果颜色中的红色成分计算如下: 150×200/255+100×(255-200)/255=139,其他分量以此类推。
10.3 颜色控制 颜色的创建可以利用Color结构的FromArgb方法完成,FromArgb方法是基于四个 8 位 ARGB 分量(alpha、红色、绿色和蓝色)值创建 Color 结构的。格式如下: ① Color.FromArgb (Int32) ② Color.FromArgb (Alpha, Color) ③ Color.FromArgb (Red, Green, Blue) ④ Color.FromArgb (Alpha, Red, Green, Blue) 含义是: ① 从一个 32 位ARGB值创建 Color 结构。32 位 ARGB 值的字节顺序为 AARRGGBB,AA 表示alpha 分量值。 RR、GG 和 BB 分别表示红色、绿色和蓝色颜色分量值。 ② 从指定的 Color 结构创建 Color 结构,使用指定的 alpha 值。 ③ 从指定的 8 位颜色值(红色、绿色和蓝色)创建 Color 结构。alpha 值默认为 255(完全不透明)。 ④ 从四个 ARGB 分量值创建 Color 结构。
10.3 颜色控制 1.用不透明和半透明的直线绘制图形 要绘制一条不透明的直线,将颜色的通道值设为255; 要绘制一条半透明的直线,将通道值设为从1~254 中的任何值。 当在背景上绘制半透明的直线时,直线的颜色和背景的颜色混合在一起。通道值接近O 的以背景色为主,接近255 的以直线色为主。 例10-10 :绘制一个位图,然后将位图作为背景在上面绘制一条直线。第一条直线通道值为255,不透明 。第二条通道值为128,看上去是半透明的,可以通过直线看到背景。代码如下,代码的运行结果为图10.10 所示。 Dim bitmap As New Bitmap("c:\picture.bmp") e.Graphics.DrawImage(bitmap, 10, 5, bitmap.Width, bitmap.Height) '在指定位置,按指定大小绘制指定的Image Dim opaquePen As New Pen(Color.FromArgb(255, 0, 0, 255), 40) Dim semiTransPen As New Pen(Color.FromArgb(128, 0, 0, 255), 40) '绘制一条连接由坐标对指定的两个点的直线 e.Graphics.DrawLine(opaquePen, 0, 40, 200, 40) e.Graphics.DrawLine(semiTransPen, 0, 100, 200, 100)
10.3 颜色控制 图10.10 绘制不透明和半透明的直线 2.用合成模式控制通道混合 创建一个脱离屏幕的位图,该位图有如下特征: ①颜色的通道值不到255 。 ②当创建位图时彼此间没有颜色混合。 ③当显示完成的位图时,位图中的颜色在显示设备上和背景色通过通道混合在一起。 常用的Graphics 对象的混合模式为CompositingMode,用来指定源色与背景色组合的方式。成员为: SourceCopy 指定在显示颜色时,改写背景色。 SourceOver 指定在显示颜色时,与背景色混合。
10.3 颜色控制 例10-11 :用Bitmap位图创建一个Graphics 对象,用半透明刷(=160)填充了一个红色的椭圆和一个绿色的椭圆。绿色的椭圆重叠在红色椭圆的上方,但绿色并没有和红色混合,因为Graphics 对象的混合模式设置为SourceCopy。代码在屏幕上绘制该位图两次:一次是在白色背景上,一次是在多色背景上。两个椭圆公共部分位图上的像素的alpha 为160 ,因此,两个椭圆在屏幕上就和背景色混合在一起,但椭圆之间不进行混合。代码如下: Dim myBitmap As New Bitmap(180, 100) '创建一个空位图及背景 Dim bitmapGraphics As Graphics = Graphics.FromImage(myBitmap) Dim redBrush As New SolidBrush(Color.FromArgb(160, 255, 0, 0)) Dim greenBrush As New SolidBrush(Color.FromArgb(160, 0, 255, 0)) bitmapGraphics.CompositingMode = CompositingMode.SourceCopy
10.3 颜色控制 bitmapGraphics.FillEllipse(redBrush, 0, 0, 150, 70) bitmapGraphics.FillEllipse(greenBrush, 30, 30, 150, 70) e.Graphics.CompositingQuality = CompositingQuality.GammaCorrected '绘制多色背景 Dim colorBrush As New SolidBrush(Color.Aqua) '浅绿色 e.Graphics.FillRectangle(colorBrush, 200, 0, 60, 100) colorBrush.Color = Color.Yellow '黄色 e.Graphics.FillRectangle(colorBrush, 260, 0, 0, 100) colorBrush.Color = Color.Fuchsia '紫红色 e.Graphics.FillRectangle(colorBrush, 320, 0, 60, 100) e.Graphics.DrawImage(myBitmap, 0, 0) '在白色背景上显示位图 e.Graphics.DrawImage(myBitmap, 200, 0) '在多色背景上显示位图
10.3 颜色控制 输出显示为图10.11所示,需要说明的是两个椭圆色和背景色混合了,却没有相互混合。 图10.11用合成模式控制通道混合(左图:白背景,右图:多色背景) 如果希望椭圆除了与背景混合外,椭圆之间也相互混合,请将上述语句更改如下: BitmapGraphics. CompositingMode=CompositingMode.SourceOver 如图10.12 所示是以上代码的运行结果。
10.4 用GDI+绘制图形 1.绘制直线、矩形和椭圆 绘制直线用DrawLine,格式为: Graphics.DrawLine (Pen, Point, Point) 在两点之间绘制一条直线 。 Graphics.DrawLine (Pen, x1, y1, x2, y2) 在坐标对指定的两点之间画线。 绘制矩形用DrawRectangles ,格式为: Graphics.DrawRectangles (Pen, Rectangle[]) 绘制由坐标对、宽度和高度指定的矩形。 Rectangle 结构存储四个整数,表示一个矩形的位置和大小。矩形由其宽度、高度和左上角定义。 若DrawRectanglese换成Rectanglese,Pen换成Brush,则画带填充的矩形。 绘制椭圆用DrawEllipse,格式为: Graphics.DrawEllipse (Pen, Rectangle) 绘制边界 Rectangle 结构指定的椭圆
10.4 用GDI+绘制图形 Graphics.DrawEllipse (Pen, x, y ,width,height) 绘制一个由边框(该边框由一对坐标、高度和宽度指定)定义的椭圆。 若DrawEllipse换成FillEllipse,Pen换成Brush,则画带填充的椭圆。 例10-12:演示了如何描绘线条、矩形和椭圆,还演示填充图形的方法,运行结果见图10.13所示。 Dim g As Graphics = e.Graphics Dim brush As SolidBrush = New SolidBrush(Color.Blue) Dim pen As Pen = New Pen(Color.CadetBlue) g.FillRectangle(brush, 90, 30, 150, 90) g.DrawLine(pen, 90, 30, 110, 40) '画连接矩形的直线 g.DrawLine(pen, 90, 120, 110, 130) g.DrawLine(pen, 240, 30, 260, 40) g.DrawLine(pen, 240, 120, 260, 130) g.DrawRectangle(pen, 110, 40, 150, 90) '画上面的矩形 brush.Color = Color.Red
10.4 用GDI+绘制图形 g.FillEllipse(brush, 280, 75, 100, 50) g.DrawLine(pen, 380, 55, 380, 100) '画两个椭圆之间的连线 g.DrawLine(pen, 280, 55, 280, 100) g.DrawEllipse(pen, 280, 30, 100, 50) 图10.13 画线、画矩形和画椭圆 在屏幕上画矩形或者画椭圆要注意第三、第四个参数分别指定矩形或者约束椭圆外接矩形的宽度和高度。
10.4 用GDI+绘制图形 2.绘制弧线 弧线是椭圆的一部分,计量单位是度。它从一个“起始角”开始,扫描指定的度数(称为“仰角”)。如果顺时针方向扫描,则指定度数为正;逆时针方向扫描,则指定度数为负。图10.14展示了两段弧线,左图从0 度向下扫描约110 度(顺时针),右图从0 度向上扫描约-110 度(逆时针)。 每段弧线实际都是椭圆的一部分(椭圆的其他部分不可见)。画一段弧线时,必须指定封闭椭圆约束矩形的尺寸,椭圆由左上角坐标和宽度、高度指定的矩形约束,约束矩形决定了椭圆大小。
10.4 用GDI+绘制图形 图10.14 正负仰角 绘制弧线用DrawArc,格式为: Graphics.DrawArc(pen, rec, startAngle , sweepAngle) 绘制一段弧线,它是Rectangle 结构约束的椭圆的一部分。
10.4 用GDI+绘制图形 Graphics.DrawArc(pen, x, y, width, height, startAngle, sweepAngle) 绘制一段弧线,它表示由一对坐标、宽度和高度指定的椭圆部分。 说明: Pen:确定弧线的颜色、宽度和样式。 x, y:约束矩形的左上角坐标。 rect: Rectangle 结构,它定义椭圆的边界。 startAngle:起始角,即从 x 轴到弧线的起始点沿顺时针方向度量的角(以度为单位)。 sweepAngle:扫过角,即从 startAngle 参数到弧线的结束点沿顺时针方向度量的角(以度为单位)。 若将DrawArc换成DrawPie方法,则完成扇形的绘制。 若将DrawPie换成FillPie方法,Pen换成Brush则完成填充扇形的绘制。
10.4 用GDI+绘制图形 例10-13:下列程序要描绘6 幅图像,包括3段弧线和3 个填充扇形。为了显示用于限定弧线大小及位置的约束矩形,程序采用和约束矩形一样的x 坐标、y 坐标、宽度和高度参数画出了这种矩形。代码如下,运行结果如图10.15所示。 Dim graphicsObject As Graphics = e.Graphics Dim rec1 As Rectangle = New Rectangle(15, 35, 80, 80) Dim brush1 As SolidBrush = New SolidBrush(Color.Firebrick) Dim pen1 As Pen = New Pen(brush1, 4) Dim brush2 As SolidBrush = New SolidBrush(Color.DarkBlue) Dim pen2 As Pen = New Pen(brush2, 1) graphicsObject.DrawRectangle(pen1, rec1) graphicsObject.DrawArc(pen2, rec1, 0, 360) '图 1
10.4 用GDI+绘制图形 rec1.Location = New Point(100, 35) graphicsObject.DrawRectangle(pen1, rec1) graphicsObject.DrawArc(pen2, rec1, 0, 110) '图2 rec1.Location = New Point(185, 35) graphicsObject.DrawArc(pen2, rec1, 0, -270) '图3 rec1.Location = New Point(15, 120) rec1.Size = New Size(80, 40) graphicsObject.FillPie(brush2, rec1, 0, 360) '图4
10.4 用GDI+绘制图形 rec1.Location = New Point(100, 120) graphicsObject.DrawRectangle(pen1, rec1) graphicsObject.FillPie(brush2, rec1, 270, -90) '图5 rec1.Location = New Point(185, 120) graphicsObject.FillPie(brush2, rec1, 0, -270) '图6 图10.15 演示弧线方法
10.4 用GDI+绘制图形 3.绘制多边形和折线 多边形是具有多个边的几何形状。绘制多边形的Graphics方法有: (1)DrawLines方法,用于描绘一系列的点连接起来的线段。如果第一个点和最后一个点坐标相同,则图形封闭。格式如下: Graphics.DrawLines (Pen, Point[]) Point 结构: 表示定义点X 和 Y 坐标的有序对。 (2)DrawPolygon 方法,用于描绘封闭多边形。格式如下: Graphics.DrawPolygon (Pen, Point[]) Point 结构:表示多边形的顶点 (3)FillPolygon方法,用于描绘填充的多边形。格式如下: Graphics.FillPolygon (Brush, PointF[]) ‘填充 Point结构指定的点数组所定义的多边形
10.4 用GDI+绘制图形 Graphics.FillPolygon (Brush, Point[], FillMode) ‘使用指定的填充模式填充多边形 FillMode:确定填充样式, 其枚举的成员为: Alternate 指定交替填充模式,是默认模式 Winding 指定环绕填充模式。 例10-14:下面的例子是三个函数绘制一个三条边的多边形的程序,运行结果见图10.16所示。 Dim myGraphicsObject As Graphics = e.Graphics Dim mypen As Pen = New Pen(Color.Blue, 4) Dim mybrush As SolidBrush = New SolidBrush(Color.Blue) Dim pointArray1 As Point()={New Point(130,100),New Point(30,200), New Point(180,300)} Dim pointArray2 As Point()={New Point(280,100),New Point(180,200), New Point(330,300)}
10.4 用GDI+绘制图形 Dim pointArray3 As Point()={New Point(430,100),New Point(330,200), New Point(480,300)} myGraphicsObject.DrawLines(mypen, pointArray1) myGraphicsObject.DrawPolygon(mypen, pointArray2) myGraphicsObject.FillPolygon(mybrush, pointArray3) 图 10.16不同效果的多边形
10.4 用GDI+绘制图形 4.绘制曲线 一条曲线通过一系列给定的点平滑地连接起来。要绘制一条曲线,可以通过以下方法: (1) 把点阵的地址传递给DrawCurve的方法 Graphics.DrawCurve(Pen, Point[]) ‘画经过指定点的曲线 Graphics.DrawCurve(Pen,Point[],tension) ‘使用指定的张力和经过Point结构指定的点画曲线 Graphics.DrawCurve(Pen,Point[],offset,numberOfSegments,tension) ‘使用指定的张力和点画曲线。 其中, offset:从 points 参数数组中的第一个元素到曲线中起始点的偏移量 numberOfSegments:起始点之后要包含在曲线中的段数 tension 大于或等于 0.0F 的值,该值指定曲线的张力
10.4 用GDI+绘制图形 例10-15 :通过5个指定的点绘制一条钟形的曲线,代码如下,运行结果见图10.17 所示。 Dim points As Point() = {New Point(0, 100),New Point (50, 80), New Point(100, 20), New Point(150, 80), New Point(200, 100) } Dim pen As New Pen(Co1or.FromArgb(255, 0, 0, 255)) e.Graphics.DrawCurve (pen, points) 通过传递给DrawCurve 方法一个tension参数(张力)改变曲线的弯曲路径,当张力为 0 时,用一条直线连接。 图10.17 经过点绘制的曲线
10.4 用GDI+绘制图形 例10-16 :通过同样一系列点绘制3 条曲线,代码如下: Dim points As Point()={New Point(20, 50), New Point(100, 10), New Point(200, 100), New Point(300, 50),New Point(400, 80)} Dim pen As New Pen(Color.FromArgb(255, 0, 0, 255)) e.Graphics . Drawcurve(pen, points, OF) e.Graphics.Drawcurve(pen, points, 0.6F) e.Graphics.DrawCurve(pen, points, 1F) 图10.18 所示为3 条曲线及其张力值,当张力值为0 时,点之间通过直线连接。 图10.18 3条曲线及其张力值
10.4 用GDI+绘制图形 (2) 用DrawClosedCurve 方法绘制一条封闭的曲线 在该曲线内,通过数组中最后的点和数组中的第1个点连接来实现封闭。格式同DrawCurve。 例10-17 :通过6 个指定的点绘制一个封闭的曲线,代码如下,运行结果见图10.19所示。 Dim points As Point() = {New Point(60, 60),New Point(150, 80), New Point (200, 40), New Point(180, 120), New Point(120, 100),New Point(80, 160)} Dim pen As New Pen(Color.FromArgb(255, 0, 0, 255)) e.Graphics.DrawClosedCurve(pen, points) 图10.19 绘制封闭曲线
10.4 用GDI+绘制图形 5.综合应用 例10-18:用绘制直线的方法绘制四瓣花形图案。运行结果如图10.20所示。 Dim x1, x2, y1, y2 As Integer Dim r, a, pi, d, c As Single Dim g As Graphics = e.Graphics Dim p As Pen = New Pen(Color.Red) pi = 3.14 d = 50 c = 1 For a = 0 To 2 * pi Step pi / 360 r = d * (c + Math.Sin(4 * a)) x1 = 120 + Int(r * Math.Cos(a)) '120和100决定图案在窗体上的起始位置 y1 = 100 + Int(r * Math.Sin(a))
10.4 用GDI+绘制图形 x2 = 120 + Int(r * Math.Cos(a + pi / 5)) y2 = 100 + Int(r * Math.Sin(a + pi / 5)) g.DrawLine(p, x1, y1, x2, y2) Next a 图 10.20 四瓣花形图案图
10.4 用GDI+绘制图形 例10-19:绘制小房子,运行结果如图10.21所示。 Dim g As Graphics = e.Graphics Dim p_roof As Pen = New Pen(Color.Brown, 3) ' 画三角形的房顶 Dim roof(2) As Point roof(0).X = 110 roof(0).Y = 0 roof(1).X = 10 roof(1).Y = 100 roof(2).X = 210 roof(2).Y = 100 g.DrawPolygon(p_roof, roof)
10.4 用GDI+绘制图形 Dim p_wold As Pen = New Pen(Color.Black, 5) ' 画长方形的房子 g.DrawRectangle(p_wold, 10, 100, 200, 200) Dim p_windows As Pen = New Pen(Color.Blue, 3) ' 画长方形的窗户1 Dim w1_x As Integer = roof(1).X + 20 Dim w1_y As Integer = roof(1).Y + 20 g.DrawRectangle(p_windows, w1_x, w1_y, 50, 60) Dim w2_x As Integer = roof(2).X – 70 ' 画长方形的窗户2 Dim w2_y As Integer = roof(2).Y + 20 g.DrawRectangle(p_windows, w2_x, w2_y, 50, 60)
10.4 用GDI+绘制图形 Dim p_Door As Pen = New Pen(Color.Green, 5) ' 画弧形的门 g.DrawArc(p_Door, w1_x + 40, w1_y + 60, 80, 245, 0, -180) 图 10.21 绘制小房子
10.5 文本处理 System.Drawing.Text命名空间提供高级GDI+排版功能,该命名空间中的类允许用户创建和使用多种字体。 1.字体和输出文本 GDI+将字样相同但字形不同的字体分组为字体系列。在GDI+中,使用四种字形形成字体系列。例如,Arial 字体系列中包含以下字体: Regular(常规)、Bold(粗体)、Italic(倾斜)、Bold Italic(粗斜体)。 在使用 GDI+ 绘制文本之前,需要构造一个 FontFamily 对象和一个 Font 对象。FontFamily 对象指定字样(例如 Arial),而 Font 对象指定字体、字形和字号。 例如下面的例子构造一个字号为 16 像素、常规字形的 Arial 字体。在代码中,传递给 Font 构造函数的第一个参数是 FontFamily 对象。第二个参数指定字体的大小,其单位由第四个参数(像素)确定。第三个参数确定字形(普通文本),代码如下。 Dim fontFamily As New Fontwainhly(“Arial”) Dim font As New Font(fontEamily, 16,FontStyle.Regular,GraphicsUnit.Pixel)
10.5 文本处理 如果需要不同的字体,只要新建Font对象即可。Font构造函数有很多用于创建自定义字体的重载版本,大多数都要求提供一个“字体名称”( Font Name)。它是一个字符串,代表系统目前支持的默认字体。常用的字体包括Microsoft SansSerif和Serif等。构造函数通常还要求传递一个“字号”( Font Size)参数和“字体样式”( Font Style)参数。字体样式是FontStyle枚举的一个成员,包括Bold , Italic,Regular,Strlkeout(删除线)和Underline等。还可以通过or运算符来组合样式,例如,Fontstyle.Italic Or FontStyle.Bold将字体变成倾斜和加粗。 执行自定义绘制时,你可能希望从指定点开始的一行上绘制文本。通过使用 Graphics 类接收 Point 或 PointF 参数的 DrawString 方法,或是使用 TextRenderer 接收Point 的 DrawText 重载,进行文本绘制。 执行定位输出文本时,希望从指定点开始输出文本。通过使用Graphics类的DrawString 方法来设置字体,并在指定位置描绘文本。它接收所需的文本、点坐标参数Brush 、Color 以及 Font参数实现文本输出。
10.5 文本处理 例10-20:字体程序示例,代码执行下列操作。 Public Sub DrawStringPointF(ByVal e As PaintEventArgs) Dim drawString As [String] = "Sample Text" ‘创建要绘制的文本字符串 Dim drawFont As New Font("Arial", 16) ‘将字体定义为 Arial (16磅) Dim drawBrush As New SolidBrush(Color.Black) ‘创建绘制所使用的实心黑色画笔 Dim drawPoint As New Point(150, 150) ‘绘制文本的左上角的点 ‘ 使用该字体、画刷和目标点将字符串绘制到屏幕。 e.Graphics.DrawString(drawString, drawFont, drawBrush, drawPoint) End Sub
10.5 文本处理 例10-21:代码采用4 种字体来显示文本,每种都采用不同的字号。运行结果如图10.22所示。 Dim g As Graphics= e.Graphics Dim brush As SolidBrush=New SolidBrush(Color.DarkBlue) Dim style As Fontstyle=Fontstyle.Bold Dim arial As Font=New Font(“Aria1”, 12, style) ‘样式1 style=FontStyle.Regular Dim timesNewRoman As Font=New Font(“Times New Roman”, 12, style) ‘样式2 style=FontStyle.Bold Or FontStyle.Italic Dim courierNew As Font =New Font (“Courier New”, 16,style) ‘样式3
10.5 文本处理 style=FontStyle.Strikeout Dim tahoma As Font = New Font(“Tahoma”, 18, style) ‘样式4 g.Drawstring(” Aria1 12 point bold.”, arial, brush, 10, 10) g.DrawString(“Times New Roman 12 point plain.”,timesNewRoman, brush,10,30) g.DrawString(“Courier New 16 point bold and italic.”,courierNew, brush,l0,54) g.DrawString(“Tahoma.Name 18 point strikeout.”, tahoma, brush, 10, 75) 图10.22 不同字体展示
10.5 文本处理 2.格式化文本 (1) 在矩形中换行输出 用接收 Rectangle参数的Graphics 类的DrawString 方法在矩形中绘制换行文本。 例10-22:在矩形中换行输出文本,代码如下,运行结果如图10.23 所示。 Dim text1 As String = " 2008北京奥运会,同一个世界,同一个梦想" Dim font1 As New Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point) Dim rectF1 As New RectangleF(30, 10, 100, 122) e.Graphics.DrawString(text1, font1, Brushes.Blue, rectF1) e.Graphics.DrawRectangle(Pens.Black, Rectangle.Round(rectF1)) 要对文本应用特殊的格式,先初始化一个 StringFormat对象,然后将该对象的地址传 递给Graphics 类的DrawString方法。 图10.23 换行输出
10.5 文本处理 (2) 居中输出文本 在窗体或控件中用StringFormat类与DrawString 方法一起使用来指定文本居中输出。 例10-23 :在一个矩形每一行文本都是居中的,并且整个文本块在矩形的中部,代码如下,运行结果如图10.24 所示。 Dim text1 As String = "2008北京奥运会,同一个世界,同一个梦想" Dim font1 As New Font("Arial", 12, FontStyle.Bold, GraphicsUnit. Point) Dim solidBrush As New SolidBrush(Color.FromArgb(255, 0, 0, 255)) Dim rect1 As New Rectangle(10, 10, 130, 140) Dim stringFormat As New StringFormat() stringFormat.Alignment = StringAlignment.Center ’文本在矩形中居中对齐 stringFormat.LineAlignment = StringAlignment.Center ’文本在行中居中对齐
10.5 文本处理 e.Graphics.DrawString(text1, font1, solidBrush, rect1, stringFormat) e.Graphics.DrawRectangle(Pens.Black, rect1) 图10.24 居中输出文本 (3) 竖排文本输出 可使用 StringFormat 对象指定在垂直方向而不是在水平方向绘制文本。 例10-24:下面的示例将值 DirectionVertical 赋给 StringFormat 对象的 FormatFlags 属性。该 StringFormat 对象被传递给 Graphics 类的 DrawString 方法。DirectionVertical 值是 StringFormatFlags 枚举的成员,表示文本垂直对齐。程序代码如下,运行结果如图10.25所示。
10.5 文本处理 Dim myText As String = "同一个世界,同一个梦想" Dim font As New Font( "Lucida Console",14,FontStyle.Regular,GraphicsUnit.Point) Dim point As New Point (40, 10) Dim stringFormat As New StringFormat() Dim solidBrush As New SolidBrush(Color.FromArgb(255, 0, 0, 255)) stringFormat.FormatFlags = StringFormatFlags.DirectionVertical e.Graphics.DrawString(myText, font, solidBrush,point,stringFormat) 10.25 竖排输出文本
10.6 图像处理 System .Drawing.Imaging命名空间提供高级的GDI+图像功能,例如翻转、缩放、剪切等,这些功能使用起来非常方便。 在VB.NET 中使用图像有两种方法。第一种方法可以使用Visual Studio. NET 工具箱中的PictureBox控件,在窗体上拖放这个控件,并在设计时或运行时提供一个对图像的引用,这是在窗体上获得一个固定图像的快捷方式。第二种方法可以使用自绘制控件中的图像。在下面的练习中,看看如何使用WroxPaint , 这样就可以不必在一个单调的、白色的背景上而是在加载的图像上进行绘制。
10.6 图像处理 1.导入图像 利用PictureBox 控件的Image 属性获取显示的图像。在默认情况下,最终派生出 UserControl 的Control 类支持Backgroundlmage 属性.而导入的图像设置了此属性,因此,图像作为背景显示。 2.平铺图像 如果调整了窗体的大小,图像就会平铺显示。更重要的是,如果控件太小则不能容纳整个图像,图像的边就被裁切了。我们希望能缩放图像,使之正好放在控件中。这就要使用 Control基类中的绘制背景图像功能,并提供Backgroundlmage 属性的新的实现方式。例如如下代码: Dim graphicsobject As Graphics= e.Graphics Dim backgroundBrush As New SolidBrush(BackColor) peventGraphics.FillRectangle(backgroundBrush,g.ClipRectangle) ‘获取要在其中进行绘画的矩形。
10.6 图像处理 Dim clienRectangle As New Rectangle(O, 0, Width, Height) g.Graphics.Drawlmage(Backgroundlmage, clientRectangle) 运行该项目图像将伸展开,以适合整个屏幕,在我们调整窗体的大小时,图像就自动调整其大小。 3、调整和缩放图像 调整功能更改图像的实际大小。宽度和高度都根据调整大小比例而变化。 缩放功能更改图像在屏幕上的大小。执行的缩放量一般表示为图像原始大小的百分比。缩放不会更改原始图像的大小,只会更改图像在屏幕上显示的大小。如果缩放图像,可以通过改变图像的宽度和高度的方法实现,也可以通过pictureBox1.SizeMode的Zoom来实现。 DrawImage 方法的一个变体接收一个 Bitmap 和一个 Rectangle。该矩形指定了绘图操作的目标,即它指定了将要在其内部绘图的矩形。如果目标矩形的大小与原始图像的大小不同,原始图像将进行缩放,以适应目标矩形。
10.6 图像处理 例10-25:下面的代码示例演示了如何将同一图像绘制三次:一次没有缩放,一次使用扩展,一次使用压缩,运行结果如图10.26所示。 Dim myGraphics As Graphics = e.Graphics Dim myBitmap As New Bitmap("Spiral.png") Dim expansionRectangle As New Rectangle(135,10,myBitmap.Width,myBitmap.Height) Dim compreRectangle As New Rectangle(300,10,myBitmap.Width/2,myBitmap.Height/2) myGraphics.DrawImage(myBitmap, 10, 10) myGraphics.DrawImage(myBitmap, expansionRectangle) myGraphics.DrawImage(myBitmap, compreRectangle)
10.6 图像处理 DrawImage 方法的一些调用方式带有源矩形参数和目标矩形参数。源矩形参数指定原始图像要绘制的部分,目标矩形参数指定将要在其内部绘制该图像指定部分的矩形。如果目标矩形的大小与源矩形的大小不同,图片将会缩放,以适应目标矩形。 图 10.26 三张图的效果 例10-26:演示如何从文件 Runner.jpg 构造一个 Bitmap。整个图像在 (0,0) 处开始绘制,无缩放。然后将该图像的一小部分绘制两次:一次使用压缩,一次使用扩展。 运行结果见图10.27所示。
10.6 图像处理 Dim myGraphics As Graphics = e.Graphics Dim myBitmap As New Bitmap("c:\Runner.jpg") Dim sourceRect As New Rectangle(80, 70, 80, 45) ' runner的一只手图案 Dim destRect1 As New Rectangle(200, 10, 20, 16) ' 缩小手图案 Dim destRect2 As New Rectangle(200, 40, 200, 160) ' 放大手图案 myGraphics.DrawImage(myBitmap, 0, 0) ' 图像源点在(0,0) myGraphics.DrawImage(myBitmap,destRect1,sourceRect,GraphicsUnit.Pixel) ' 画缩小的手图案 myGraphics.DrawImage( myBitmap, destRect2, sourceRect, GraphicsUnit.Pixel) '画放大的手图案
10.6 图像处理 图10.27 显示了未缩放的图像,以及压缩的和扩展的图像部分 4.翻转和旋转图像 4.翻转和旋转图像 翻转沿 x 轴或 y 轴进行,结果将产生一个镜像或颠倒的图像。旋转围绕图像的中心按一定度数转动图像。对于图像,最常见的是按 90 度的倍数进行旋转。实现方式是: Graphics.RotateTransform:旋转应用于 Graphics类的对象的变换中 mage.RotateFlip方法: 翻转或者同时旋转和翻转图像。
10.6 图像处理 例如:在“解决方案资源管理器”->“我的项目”->“项目设计器”->击“资源”选项卡->“添加资源”->, “添加图像文件”,在Pain方法中输入实现旋转的代码。 方法1:e.Graphics. RotateTransform (45) ’旋转45度 e.Graphics.DrawImage(My.Resources.picture, 50, 0) 方法2:e.Image.RotateFlip(RotateFlipType.Rotate180FlipY) ’旋转180度,垂直翻转 Dim bitmap1 As Bitmap bitmap1.RotateFlip(RotateFlipType. Rotate270FlipNone) ’旋转270 度,不翻转 5.裁剪图像 例10-27:用苹果图案构造裁剪效果。先按照原始尺寸绘制整个图像。然后,调用 Graphics 对象的 DrawImage 方法,在大于图像的目标矩形中绘制该苹果图像的一部分来实现裁剪。代码如下,运行结果如图10.28所示。
10.6 图像处理 DrawImage 方法通过查看源矩形来确定要绘制苹果的哪部分,这由第三个参数及相关矩形坐标来指定。在本例中,苹果在宽度和高度上均被裁切为原始尺寸的75%。 DrawImage 方法通过查看目标矩形来确定在何处绘制裁切后的苹果以及裁切后的苹果大小,这由第二个参数指定。在本例中,目标矩形在宽度和高度上都比原始图像大30%。 Dim image = New Bitmap("Apple.bmp") e.Graphics.DrawImage(image, 0, 0) ‘在(0, 0)绘原始尺寸的图像 Dim width As Integer = image.Width Dim height As Integer = image.Height Dim destinationRect As New RectangleF(150,20,1.3F * width,1.3F * height) ' 在(150,20)设定的目标区域比原始尺寸放大30% '依比例绘苹果图像的一部分以便填满矩形区域
10.6 图像处理 Dim sourceRect As New RectangleF(0, 0, 0.75F * width, 0.75F * height) ’裁切为原始尺寸的 75% e.Graphics.DrawImage( image,destinationRect,sourceRect, GraphicsUnit.Pixel) 图10.28 显示原始苹果和缩放、裁切后的苹果
10.7 简单的动画设计 在VB.NET 的程序中,适当地加入一些动画效果会给枯燥的程序增加活力。本节将介绍一些简单的动画设计的编程技巧。 在介绍动画设计之前先了解一些动画的原理。动画可分为两种:位移动画和翻页动画。位移动画可以简单地理解为由于图像位置变动而产生的动画效果,例如,一个红太阳从下到上的位移变化过程就给人们一种太阳冉冉升起的视觉动画效果。翻页动画是一些预先制作好的图形文件,在屏幕上不间断地切换。该组图片在极短的时间间隔内更替,于是产生了动画的视觉效果。
10.7 简单的动画设计 1.位移动画编程设计 位移动画设计需要利用PictureBox和Timer两个基本控件。 PictureBox是窗口图片箱控件,用来显示位图、图元文件、图标、JPEG 、GIF 或PNG 类型的图像。在设计时将需要显示图片的类型由Image 属性设置,在显示区域对图像的裁剪和定位由SizeMode 属性控制,在PictureBoxSizeMode 枚举类型中设置SizeMode 属性值改变显示区域的尺寸。默认情况下,PictureBox控件显示时没有边界,可以用BorderStyle 属性提供一个标准或三维边界,用来从剩下的窗体中分辨图片箱。
10.7 简单的动画设计 例10-28:ShowMylmage 为已存在的窗体添加代码。 Private MyImage As Bitmap Public Sub ShowMyImage(fileToDisplay As String, xSize As Integer, ySize As Integer) If Not (Mylmage Is Nothing) Then Mylmage. Dispose () End If ’枚举值StretchImage表示图像被拉伸或收缩,以适合显示区域的大小 pictureBox1.SizeMode=PictureBoxSizeMode.StretchImage Mylmage = New Bitmap(fileToDisplay) pictureBoxl.ClientSize = New Size(xSize, ySize) pictureBox1.Image = CType(Mylmage, Image) End Sub
10.7 简单的动画设计 (2) Timer 控件 Timer 控件为用户自定义的时间间隔事件实现计时,该控件必须用在窗口中,时间间隔的长度由 Interval 属性定义,其值以毫秒为单位。若启用了该控件,则每个时间间隔引发一个Tick事件,要执行的代码添加在该事件中。Timer控件的主要方法包括 Start 和 Stop,这两种方法可以打开和关闭计时器。计时器在关闭时重置,不存在暂停 Timer控件的方法。 无论何时Enabled 属性设置为True且该Interval 属性大于0 ,该Tick 事件以Interval属性设置为基础在时间间隔内被唤醒。该类提供设置时间间隔、开始和结束计时器的方法。 声明格式为: Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As_ System.EventArgs) Handles Timer1.Tick Tick 事件每隔一定时间发生一次,这个间隔取决于上述Interval属性。例如,Timerl 的Interval 设为1000。在该函数体中添加B = B 十1 语句,则每隔1秒B值加1。下面举例说明如何做一个简单的动画。
10.7 简单的动画设计 例10-29:用Picturebox加载一张小猫图片,通过Timerl 的Tick事件的时间间隔将小猫的位置向右移动,实现小猫走动的动画。当小猫走过右边界时,又有小猫从左边走出,直到按Stop 键停止。 新建一个顶目,将工具箱内的Timer和Picture控件加载到窗体中。 (1) 将Timer的Interval 属性设为200 , Enabled 属性设为False 。 (2) 设置Picturebox的Image 属性。任意选择一个已存在的小猫的图形文件。 (3) 添加两个命令按钮Button1(Text属性设为Move)和Button2 (Text属性设为Stop),代码如下: Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As_ System.EventArgs) Handles Timer1.Tick PictureBox1.Location = New Point(PictureBox1.Location.X + 10,_ PictureBox1.Location.Y) If PictureBox1.Location.X >= 200 Then PictureBox1.Location = _ New Point(10, PictureBox1.Location.Y) End Sub
10.7 简单的动画设计 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As_ System.EventArgs)Handles Button1.Click Timer1.Enabled = True End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As_ System.EventArgs) Handles Button2.Click Timer1.Enabled = False 2. 翻页动画编程设计 通过为Pictureboxl 的Image 连续地更换图片来完成翻页功能,例如图10.29 所示。如果把由小到大要显示的椭圆的图片用数字1~9做文件名,放在c:\,那么在很短时间内轮换显示,即可产生动画效果。
10.7 简单的动画设计 例10-30:设置Timer 的Interval 属性为200 ,添加两个命令按钮用来表示播放和停止。 在代码窗口中填写代码如下。 Public imgflag As Integer = 1 Public str$ Const filename$ = "c:\“ Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As_ System.EventArgs)_ Handles Timer1.Tick imgflag = imgflag + 1 If imgflag = 9 Then imgflag = 1 str$ = filename$ & imgflag & ".bmp" PictureBox1.Image = Image.FromFile(str$) PictureBox1.Refresh() End Sub
10.7 简单的动画设计 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As_ System.EventArgs) Handles Button1.Click Timer1.Enabled = True End Sub Private Sub Button2_Click_1(ByVal sender As System.Object, ByVal e As_ System.EventArgs) Handles Button2.Click Timer1.Enabled = False 按F5 键调试,单击Move 按钮开始动画,单击Stop按钮结束动画。 图10.29 要显示的6 张图片
本章小结 本章介绍了VB.NET 的一些图形功能以及如何构建一些简单的绘图程序。 首先介绍了与绘图密切相关的GDI+和GDI+的坐标系统,然后介绍利用GDI+绘图。Graphics类封装了GDI+的绘图画板,是GDI+绘图的核心类,所以先创建Graphics对象,然后才可以使用GDI+绘制线条和形状、呈现文本或显示与操作图像。 绘制和操作图形可以利用Pen类。Pen类用于绘制线条、勾勒形状轮廓或呈现其他几何表示形式。Pen 对象存储要绘制项的颜色、宽度和线型属性,将 Pen 对象作为参数之一传递给绘制方法,然后进行轮廓的描绘。还可以利用Brush类,Brush类用指定的颜色、样式、纹理来填充封闭的图形。GDI+提供了Brush及其派生类来填充内部轮廓,包括单色填充图形的SolidBrush类,用阴影样式、前景色和背景色填充的HatchBruh类,用一个图像填充的TextureBrush 类,用直线形颜色渐变填充图形的LinearGradientBrush类和用路径形颜色渐变填充图形的pathGradientBrush类。
本章小结 在GDI+中实现颜色控制用Color 结构,Color 结构用来描述对象的颜色和透明度,以及定义处理颜色的方法和常量。颜色是一个32 位的值,由红色、绿色、蓝色及通道组成。颜色的创建可以利用Color结构的FromArgb方法完成,FromArgb方法是基于四个 8 位 ARGB 分量(alpha、红色、绿色和蓝色)值创建Color结构。 用GDI+绘制的图形有画直线DrawLine,画矩形DrawRectangles,画椭圆DrawEllipse,画弧线DrawArc和画多边形和折线的DrawLines、DrawPolygon 和FillPolygon方法。还可以构造和绘制曲线:用DrawCurve和DrawClosedCurve 方法。 System.Drawing.Text命名空间提供高级GDI+排版功能,该命名空间中的类允许用户创建和使用多种字体,实现文本处理。在使用 GDI+ 绘制文本之前,需要构造一个FontFamily 对象和一个 Font 对象。FontFamily 对象指定字样(例如 Arial),而 Font 对象指定字体、字形和字号。格式化文本可以指定在矩形中换行输出和在窗体或控件中使文本居中输出,还可以使用 StringFormat 对象指定在垂直方向还是在水平方向输出文本。
本章小结 System .Drawing.Imaging命名空间提供高级的GDI+图像功能,例如翻转、缩放、剪切等,这些功能使用起来非常方便。在VB.NET 中使用图像有两种方法。一是使用Visual Studio. NET 工具箱中的PictureBox控件;二是使用自绘制控件中的图像。 在VB.NET 的程序中,适当地加入一些动画效果会给枯燥的程序增加活力。本章介绍了一些简单的动画设计的编程技巧。包括:位移动画和翻页动画的原理和实现方法。具体为:利用PictureBox和Timer两个基本控件实现位移动画设计。通过为Pictureboxl 的Image 在很短时间连续地更换图片来完成翻页动画设计。