单元七 图形图像处理1
[学习目标] 熟悉VB.NET绘制图形的有关概念、常用的类、对象、属性和方法等基础知识,熟悉开发绘制图形、浏览图像、图形动画程序的流程、方法、和技巧。
7.1 图形的绘制
[案例7-1] 仿Windows画图程序
本案例模仿Windows画图程序,有菜单栏和工具栏。单击工具栏上的相应按钮选择要画的图形;在画笔颜色处单击色块调出调色板,选择颜色;单击画笔宽度中需要的线条决定所画边框的粗细。将鼠标移到绘图区相应的位置按住左键拖到适当位置放开,即绘出了相应图形。此案例的运行界面如图7-1所示。
[技能目标]
1.熟悉Point/Pointf、Size/Sizef、Rectangle/Rectanglef对象。
2.熟悉颜色、画笔、画刷的使用方法。
3.熟悉Graphics的各种绘绘制图形的方法。
4.掌握图形的平移变换、旋转变换和比例变换的方法。
图7-1 仿Windows画图程序主界面
[操作要点与步骤]
1.建立一个新的Windows应用程序,命名为vbnet7-1。
2.在窗体上添加如下控件:一个Mainmenu控件设计菜单,一个ToolBar控件设计绘图工具栏,一个PictureBox作为本程序画板,用二个Lable控件让用户选择颜色和选择画笔宽标志,5个button控件让用户选择画笔宽度,一个ColorDialog 控件做调色板,一个ImageList控件,一个OpenFileDialog控件,一个StatusBar作为状态信息栏。调整窗体上各控件的大小及位置。
表7-1 画图程序各控件属性设置
Form Form1 Text Vbnet7-1
Icon Mydraw.ico
Menu MainMenu1
Mainmenu Mainmenu1
mFile text 文件(&F)
mNew text 新建(&N)
mExit text 退出(&X)
MenuItem1 text 编辑(&E)
MenuItem3 text 复制(&C)
MenuItem4 text 剪切(&V)
MenuItem5 text 粘贴(&P)
ToolBar ToolBar1 ImageList ImageList1
ShowTip Ture
ImageList ImageList1 TransparentColor TransParent
OpenFileDialog OpenFileDialog1 Filter 图标文件|*.ico
ColorDialog ColorDialog1 Color Black
lbcolor Lbcolor1 BackColor Blue
StatusBar StatusBar1 ShowPannels Ture
StatusBarPanel1 text 制作人:
BorderStyle Raised
AutoSize Contents
StatusBarPanel2 text Wendy
BorderStyle Raised
AutoSize None
StatusBarPanel3 text 版本:
BorderStyle Raised
AutoSize Contents
StatusBarPanel4 text Ver1.0
BorderStyle Raised
AutoSize None
PictureBox PictureBox1 BackColor White
Button Butpen1 Backcolor Black
Butpen2 Backcolor Black
Butpen3 Backcolor Black
Butpen4 Backcolor Black
Butpen5 Backcolor Black
label Label1 text 画笔颜色
Label2 text 画笔宽度
为ImageList1控件添加图标。
单击ImageList1的Images属性右侧的"…"按钮,弹出如图7-2所示"Image集合编辑器"对话框,在窗口中单击"添加"按钮为ImageList1添加图标。
没有设置的控件属性均为默认值,以后的案例中属性说明与此相同。
4.为工具栏ToolBar控件添加按钮。
单击ToolBar1控件的Buttons属性右侧的"…"按钮,弹出"ToolBarButton集合编辑器",在窗口中单击"添加"按钮为ToolBarButton1添加按钮。
除了TPencil1按钮的Pushed属性为True外,其余按钮的Pushed属性均为False,即程序刚运行时,只有"铅笔工具"的按钮处于按下状态,默认用户选择的是"铅笔工具"。
5.以上步骤完成了界面设计及控件属性设置,可进行代码编写了。
(1)在Form1类里定义全局变量和mSelect枚举。
Dim g As Graphics '定义Graphics对象
Dim pstart As Point,pend As Point '定义画图的起始点,终点
Dim mChoice As Integer '选择图形枚举
Dim mWidth As Integer '画笔宽度
Dim mIcon As Icon '用户选择图标
Enum mSelect '选择图形类别枚举
Pencil '铅笔
Line '直线
Rec '矩形
FillRec '填充矩形
StyleRec '风格矩形
Ellipse '椭圆
FillEllipse '填充椭圆
StyleEllipse '风格椭圆
Icon '图标
Eraser '橡皮
End Enum
(2) 在Form1的Load事件中初始化全局变量和Graphics对象。
Private Sub Form1_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles MyBase.Load
g = PictureBox1.CreateGraphics
mChoice = mSelect.Pencil '默认选择为铅笔工具
mWidth = 2 '初始化画笔宽度
End Sub
(3) 定义转换坐标起点和终点的过程Convert_Point()。转换坐标起始点和终点,确保起始点始终在终点的左上方。代码如下:
Private Sub Convert_Point()
Dim ptemp As Point '用于交换的临时点
If pstart.X < pend.X Then
If pstart.Y > pend.Y Then
ptemp.Y = pstart.Y
pstart.Y = pend.Y
pend.Y = ptemp.Y
End If
End If
If pstart.X > pend.X Then
If pstart.Y < pend.Y Then
ptemp.X = pstart.X
pstart.X = pend.X
pend.X = ptemp.X
End If
If pstart.Y > pend.Y Then
ptemp = pstart
pstart = pend
pend = ptemp
End If
End If
End Sub
(4) 双击ToolBar1控件,编写ToolBar1的 ButtonClick事件代码:
'工具栏按钮单击事件
Private Sub ToolBar1_ButtonClick(ByVal sender As System.Object,ByVal e As_
System.Windows.Forms.ToolBarButtonClickEventArgs) Handles ToolBar1.ButtonClick
Dim i As Integer
For i = 0 To ToolBar1.Buttons.Count - 1
'使每个按钮都处于未按下状态
ToolBar1.Buttons.Item(i).Pushed = False
Next
'记录选择的图形
mChoice = ToolBar1.Buttons.IndexOf(e.Button)
e.Button.Pushed = True '用户单击的按钮处于按下状态
If mChoice = mSelect.Icon Then
'如果选择的是画图标,则打开OpenFileDialog选取图标
If OpenFileDialog1.ShowDialog = DialogResult.OK Then
mIcon = New Icon(OpenFileDialog1.FileName)
End If
End If
End Sub
(5) 双击lbcolor控件,进入lbcolor的Click事件,选择画笔颜色。代码如下:
Private Sub lbcolor_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)_
Handles lbcolor.Click
'打开调色板,并把用户选择的颜色赋给lbcolor的背景色
If ColorDialog1.ShowDialog = DialogResult.OK Then
lbcolor.BackColor = ColorDialog1.Color
End If
End Sub
(6) 编写选择画笔宽度的共享事件过程btnpen_Click()代码。
Private Sub btnpen_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) _
Handles btnpen1.Click,btnpen2.Click,btnpen3.Click,btnpen4.Click,btnpen5.Click
'把所有按钮的背景色都设为Black
btnpen1.BackColor = Color.Black
btnpen2.BackColor = Color.Black
btnpen3.BackColor = Color.Black
btnpen4.BackColor = Color.Black
btnpen5.BackColor = Color.Black
'用户选中的按钮背景色为Blue
CType(sender,Button).BackColor = Color.Blue
'把画笔宽度设为用户选择按钮的Tag值
mWidth = CType(sender,Button).Tag
End Sub
(7) 为 PictrueBox1的MouseDown(鼠标按下)事件编写代码。
在Form1的代码窗口中,在左侧的对象下拉列表框中选择PictureBox1,然后在右侧的事件下拉列表框中选择MouseDown,此时代码编辑器中已经自动生成了PictureBox1_MouseDown的事件码,并把鼠标定位于事件过程内部的第一行,在该过程中编写如下代码。
'画板鼠标按下事件
Private Sub PictureBox1_MouseDown(ByVal sender As Object,ByVal e As_ System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
If e.Button = MouseButtons.Left Then
'如果用户按下的是鼠标左键,则将当前点坐标赋给起始点
pstart.X = e.X
pstart.Y = e.Y
End If
End Sub
(8)为 PictrueBox1的MouseUp(鼠标释放)事件编写代码。
'画板上用户按下鼠标后又释放的事件
Private Sub PictureBox1_MouseUp(ByVal sender As Object,ByVal e As_
System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
If e.Button = MouseButtons.Left Then
'如果用户按下的是鼠标左键,记录终点坐标
pend.X = e.X
pend.Y = e.Y
'根据保存的mChoice绘制图形
Select Case mChoice
Case mSelect.Line '用户在工具栏中选择的是铅笔
Dim pen1 As New Pen(lbcolor.BackColor,mWidth)
g.DrawLine(pen1,pstart,pend) '根据起点和终点绘制直线
Case mSelect.Rec '用户在工具栏中选择的是空心矩形
Convert_Point() '转换矩形的起点为其左上点
Dim pen1 As New Pen(lbcolor.BackColor,mWidth)
g.DrawRectangle(pen1,pstart.X,pstart.Y,_
pend.X - pstart.X,pend.Y - pstart.Y) '根据起点和终点绘制空心矩形
Case mSelect.FillRec '用户在工具栏中选择的是填充矩形
Convert_Point() '转换矩形的起点为其左上点
Dim rec As New Rectangle(pstart.X,pend.Y - pstart.Y) '根据起点和终点定义矩形
Dim sbr As New SolidBrush(lbcolor.BackColor) '定义画刷颜色为用户选择的颜色
g.FillRectangle(sbr,rec) '绘制填充矩形
Case mSelect.StyleRec '用户在工具栏中选择的是风格矩形
Convert_Point() '转换矩形的起点为其左上点
Dim rec As New Rectangle(pstart.X,pend.Y - pstart.Y) '根据起点和终点定义矩形
' 定义画刷风格为Cross型,前景色为白色,背景色为用户选择
Dim hbr As New HatchBrush(HatchStyle.Cross,Color.White,lbcolor.BackColor)_
g.FillRectangle(hbr,rec) '用画刷填充矩形
Case mSelect.Ellipse '用户在工具栏中选择的是空心椭圆
Convert_Point() '转换椭圆外接矩形的起点为其左上点
Dim pen1 As New Pen(lbcolor.BackColor,mWidth)
g.DrawEllipse(pen1,pend.Y - pstart.Y) '根据椭圆外接矩形的起点和终点绘制椭圆
Case mSelect.FillEllipse '用户在工具栏中选择的是填充椭圆
Convert_Point() '转换椭圆外接矩形的起点为其左上点
Dim rec As New Rectangle(pstart.X,pend.Y - pstart.Y) '定义椭圆的外接矩形
Dim sbr As New SolidBrush(lbcolor.BackColor) '定义画刷颜色为用户选择的颜色
g.FillEllipse(sbr,rec) '用画刷填充矩形
Case mSelect.StyleEllipse '用户在工具栏中选择的是风格椭圆
Convert_Point() '转换椭圆外接矩形的起点为其左上点
Dim rec As New Rectangle(pstart.X,pend.Y - pstart.Y) '定义椭圆的外接矩形
' 定义画刷风格为Cross型,前景色为白色,背景色为用户选择
Dim hbr As New HatchBrush(HatchStyle.Cross,lbcolor.BackColor)_
g.FillEllipse(hbr,rec) '用画刷填充矩形
End Select
End If
End Sub
(9) 为 PictrueBox1的MouseMove(鼠标移动)事件编写代码。
'画板鼠标移动事件
Private Sub PictureBox1_MouseMove(ByVal sender As Object,ByVal e As_
System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If e.Button = MouseButtons.Left Then
'如果用户按下的是鼠标左键,根据保存的mChoice绘制图形
Select Case mChoice
Case mSelect.Pencil '用户在工具栏中选择的是铅笔
Dim pen1 As New Pen(lbcolor.BackColor,mWidth)
pend.X = e.X
pend.Y = e.Y
g.DrawLine(pen1,pend)
pstart = pend '将已经绘制的终点作为下一次的绘制的起点
Case mSelect.Eraser '用户在工具栏中选择的是橡皮
Dim pen1 As New Pen(Color.White,mWidth) '定义白色画笔作为擦除效果
pend.X = e.X
pend.Y = e.Y
g.DrawLine(pen1,pend) '将已经绘制的终点作为下一次的绘制的起点
pstart = pend '将已经绘制的终点作为下一次的绘制的起点
End Select
End If
End Sub
(10) 为 PictrueBox1的Mouse的Click(鼠标单击)事件编写代码。
Private Sub PictureBox1_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles _
PictureBox1.Click
If mChoice = mSelect.Icon Then
'画图标
g.DrawIcon(mIcon,pstart.Y)
End If
End Sub
'"新建"菜单项单击事件
Private Sub mNew_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles _
mNew.Click
PictureBox1.Refresh() '刷新PictureBox1
End Sub
(12) 为mExit"退出"菜单的Click事件编写代码。
Private Sub mExit_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles _
mExit.Click
Application.Exit() '退出程序
End Sub
至此,基本代码编写完成,按F5或工具栏上的运行按钮,即可运行程序,用户可以画图了。
[相关知识]
图形程序设计需用到相关基础支持类与结构,如位置、大小,常用点(Point)、矩形(Rectangle)、大小(Size)等Structure(结构)来表示范围。
1. Point/Pointf结构
Point/Pointf结构主要用于设置控件在窗体中所在位置的坐标点,即表示一个二维(X,Y)坐标。二者差别在于:Point使用整数坐标,而Pointf使用单精度浮点数据类型坐标。
(1)声明方法
Point结构声明方法如下:
Dim p As New Point(整数X,整数Y)
例:
Dim p As New Point(10,20) '定义了一个X坐标是10,Y坐标是20的点
Pointf结构声明与Point相似,即直接指定坐标点X、Y的单精度浮点数值,方法如下:
Dim p As New Pointf(单精度浮点X,单精度浮点Y)
①Offset方法
功能:设置坐标点位移。例如:
Dim p As New Point(10,20) '定义一个坐标为(10,20)的点
p.offset(20,30) '将p点平移到坐标为(30,50)处
②Equals方法
功能:表示如果两个点的坐标相同,则返回True,否则返回False。
③IsEmpty属性
功能:如果某点的X坐标和Y坐标都是为0,则返回True,否则返回False。
例:
Dim x As Boolean '定义一个逻辑变量x
Dim p As New Point(0,0) '定义一个坐标点为(0,0)的点
x = p.IsEmpty() 'x的值是逻辑True
2. Size/Sizef结构
Size/Sizef是GDI+绘图中常用到的结构,用Width(宽度)和Height(高度)两个属性来表示其大小。
声明方法:Dim s As New Size(Width,Height)
3. Rectangle/Rectanglef结构
Rectangle/Rectanglef结构用来定义一个矩形区域,二者区别在于Rectangle结构的坐标是整型,Rectanglef结构的坐标是浮点型。
(1)声明方法:
Dim r As New Rectangle(X,Y,Width,Height)
例如:创建一个左上角X坐标是20,Y坐标是30,宽度是10,高度是15的矩形代码如下:
Dim rec As New Rectangle(20,30,10,15)
Top属性 矩形最上边缘的Y坐标
Bottom属性 矩形最下边缘的Y坐标
Left属 矩形最左边缘的X坐标
Right属性 矩形最右边缘的X坐标
Location属性 矩形左上角坐标
Size属性 矩形大小
IsEmpty属性 若矩形Width、Height、X、Y属性值均为0,则此属性返回值为True,否则为False
Equals方法 若两个矩形大小和位置相同,则返回值为True,否则为False
InterSectWidth方法 如果一个矩形与另一个矩形相交,则返回True,否则为False
与VB6.0一样,在VB.NET中也是以所在控件容器的最左最上一点作为坐标系统原点。
1. 颜色
颜色是绘图功能中非常重要的一部分,在VB.NET中颜色用Color结构和Color列举来表示。Color结构中颜色由4个整数值Red、Green、Blue和Alpha表示。其中Red、Green、Blue可简写成R、G、B,表示颜色的红、绿、蓝三原色;Alpha表示不透明度。
(1)使用FromArgb方法设置颜色
语法格式:Color.FromArgb([A,]R,G,B)
功能:由透明度、红、绿、蓝来调配颜色。
说明:
A透明参数:其值为0至255,数值越小越透明。0表示全透明,255表示完全不透明。A可缺省,其默认值为255。R、G、B为颜色参数不可缺省。(R,G,B)合成原理如图7-3如示:
例:
(255,0,0)为红色
(0,255,0)为绿色
(0,0,255)为蓝色
(255,0,255)为紫色
(2)获取Color结构的各颜色分量值
VB.NET中可获取对象Color的四个自变量的值,其语法如下:
R=对象.Color.R
G=对象.Color.G
B=对象.Color.B
例:取出PictureBox1控件背景的R自变量值。
R=PictureBox1.BackColor.R
(3)用Color列举设置颜色
使用Color列举可直接指定系统定的颜色,这些被定义的颜色均用英文命名,有140多个,常用的有Red、Green、Blue、Yellow、Brown、White、Gold、Tomato、Pink、SkyBlue、Orange等列举名称。使用语法如下:
Color.颜色列举名称
例:将Button1控件背景设成蓝色。
Button1.BackColor=Color.Blue
Color列举颜色不必背记,在编辑程序代码时,只要输入"Color.",系统会自动列出这些英文名称,程序员选择其中之一即可。
2. 画笔
画笔(Pen)可在Graphics画布对象上绘制图形,只要指定画笔对象的颜色与粗细,配合相应的绘图方法,就可绘制图形形状、线条和轮廓。画笔类中封装了线条宽度、线条样式和颜色等。
(1)Pen类的主要属性
Pen类主要属性如表7-3所示。
表7-3 Pen类主要属性
属性 相关说明
DashStyle属性 线条所使用的破折号样式
PenType属性 线条使用的画笔类型
(2)声明画笔对象
声明画笔对象有两种方式,语法如下:
Dim 画笔对象 As New Pen(颜色 [,粗细])
或
Dim 画笔对象 As Pen
例:Dim mpen As New Pen(Color.Red) '创建颜色为红色的画笔
当缺省画笔粗细自变量时,系统默认为1 Pixel(象素)。
(3)重新设置画笔对象颜色与粗细。
语法如下:
画笔对象.Color=颜色
画笔对象.Width=粗细
3.画刷
画笔对象描给图形的边框和轮廓,若要填充图形的内部则必须使用画刷(Brush)对象。使用画刷对象时,也要配合FillRectangle、FillPolygon、FillEllipse、FillPie等绘图方法。
GDI+提供了几种不同形式的画刷,如SolidBrush、TextureBrush、HatchBrush等。这些画刷都是从System.Drawing.Brush基类中派生的。
(1)SolidBrush画刷
这种画刷指定了填充区域的颜色,是最简单的一种,其创建方法如下:
Dim br As SolidBrush = New SolidBrush(Color.Yellow) '定义黄色填充
(2)TextureBrush画刷
这种画刷定义了用图形填充图像内部区域的刷子,它可以用Image属性或其构造函数来定义画刷填充的图像。创建方法如下:
Dim bm As New Bitmap("star.ico") '指定填充的位图
Dim brush As New TextureBrush(bm)
(3)HatchBrush画刷
这是一种复杂的画刷,它通过绘制一种样式来填充区域,创建方法如下:
Dim brush As New HatchBrush(HatchStype.Cross,Color.Black)
其中第一个参数是画刷的填充样式,第二个参数定义了填充的前景色,第三个参数定义了填充的背景色。
使用HatchBrush对象前,需要先导入System.Drawing.Drawing2D命名空间,即在代码开头加上语句:Import System.Drawing.Drawing2D。
1.Graphics类
通常绘图时,画布是必须的。在VB.NET中进行计算机绘图时同样需要类似的画布,然后再使用画笔或画刷配合相应的绘图方法做画。Graphics类可用来建立一个画布对象,还可清理和释放画布对象。
(1)声明和建立画布对象
语法:
Dim画布对象 As Graphics
画布对象=对象.CreateGraphics()
功能:在指定的控件或对象中建立一个可以用绘图对象绘图的画布对象。
例:
在窗体内建立一个名叫g的画布对象
Dim g As Graphics
g=Form1.CreateGraphics()
如果画布对象放置在当前窗体上,则当前窗体名可省略,即使用g= CreateGraphics()
(2)清理画布对象
若需将画布对象的内容清理,只要设置画布对象的底色即可,可使用下面的语法:
画布对象.Clear(颜色)
说明:
颜色可以使用Color对象类或Color列举。
例:将画布对象清理为粉色
g.Clear(Color.Pink)
若将画布清理为原控件的底色,可用"对象.Refresh()"语句。
例:清理目前在窗体上所绘制图形
Refresh()
pictureBox1.Refresh()
(3)释放画布对象
可以用Graphics类的的Dispose函数释放用CreateGraphics()创建的Graphics对象的资源。在调用Dispose函数后,画布对象将从内存中删除,不能再被使用。
语法:
画布对象.Dispose()
例:删除画布对象g
g.Dispose()
2.Graphics的常用绘图方法
在VB.NET中,Graphics类提供了很多绘图方法,具体介绍如下。
以下举例均在已定义画布对象g的情况下。
(1)画线(DrawLine)方法
语法:
DrawLine(画笔,起点Point,终点Point)
或
DrawLine(画笔,起点X坐标,起点Y坐标,终点X坐标,终点Y坐标)
例:绘制一条起点坐标为(0,0),终点坐标为(150,150)的直线代码如下:
Dim pt1 As Point(0,0)
Dim pt2 As Point(150,150)
g.DrawLine(pen1,pt1,pt2)
或
g. DrawLine(pen1,150,150)
(2)DrawRectangle方法
语法:DrawRectangle(画笔,Rectangle对象)
例:画一个左上角坐标为(10,10),宽度为100,高度为200的矩形代码如下:
Dim pen1 As New Pen(Color.Red)
Dim s As New Size(100,200)
Dim pt As New Point(10,10)
Dim rec As New rectangle(pt,s)
g.DrawRectangle(pen1,rec)
(3)DrawEllipse方法
语法:
DrawEllipse(画笔,椭圆的外接矩形)
或
DrawEllipse(画笔,椭圆的外接矩形左上角X坐标,Y坐标,外接矩形宽度,高度)
功能:
绘制空心椭圆/圆。
绘制椭圆时各参数如图7-4所示。
例:绘制外接矩形左上角坐标是(10,10),椭圆宽度为200,高度为300的椭圆。
Dim s As New Size(200,300)
Dim pt As New Point(10,10)
Dim rec Aa New Rectangle(pt,s)
g.DrawEllipse(pen1,rec)
下面是上例的等效代码:
Dim x,y,width,height as Integer
X=10
Y=10
Width=200
Height=300
g.DrawEllipse(pen1,x,height)
Graphics类中没有专门用来绘制圆的函数,可以用DrawEllipse来实现,若外接矩形是正方形,则绘制的是圆。
DrawArc DrawArc(画笔,椭圆外接矩形,开始角度,扫过的角度) 绘制椭圆/圆的一段弧。例:在画布对象g上用画笔p绘制一个弧形,角度由2700到900。g.DrawArc(p,50,60,100,70,270,90)
DrawPie DrawPie(画笔,椭圆外接矩形,开始角度,扫过角度) 绘制空心的扇形图。例:在画布g上用画笔p绘制一个扇形,角度由2700画到1800。Dim rec As Rectangle(50,70)g.DrawPie(p,rec,-90)
DrawPolygon DrawPolygon(画笔,Point数组) 绘制一个Point数组中的点构成的多边形。
DrawClosedCurve DrawClosedCurve(画笔,Point数组) 绘制Point数组中的点构成的封闭曲线。
DrawIcon DrawIcon(画笔,绘制点X坐标,绘制点Y坐标)或DrawIcon(画笔,绘制图标的范围矩形) 在指定的坐标中绘图标。
(5)DrawString方法
语法:
DrawString(文本,字体,画刷,X坐标,Y坐标)
功能:绘制字符串文本。
例:
Dim brush As New SolidBrush(Color.Black) '定义画刷
Dim font1 As New Font('Arial Black',36) '定义字体
g.DrawString("Welcome to VB.NET!",font1,brush,100)
(6)填充方法
画刷配合填充方法可以填满图形内部颜色,Graphics类的填充方法有FillRectangle、FillEllipse、FillPolygon、FillClosedCurve、FillPie等。它们与Draw开头的方法一一对应,输入参数也与相应的Draw方法一致,其语法定义如下:
FillRectangle(画刷,矩形) '填充矩形
FillEllipse(画刷,椭圆的外接矩形) '填充椭圆
FillPolygon(画刷,坐标点数组) '填充多边形
FillClosedCurve(画刷,坐标点数组) '填充封闭曲线
FillPie(画刷,椭圆外接矩形,开始角度,扫过角度) '填充扇形
例:以下是一个填充实例。
Dim brush As New SolidBrush(Color.Black)
Dim rec As New Rectangle(10,80)
g.FillRectangle(brush,rec) '填充矩形
Dim pt(5) As Point
pt(1)=New Point(50,100)
pt(2)=New Point(100.200)
pt(3)=New Point(10,400)
pt(4)=New Point(50,200)
pt(5)=New Point(50,100)
g.FillPolygon(brush,pt) '填充多边形
Dim stattAngle As Single=0.0F
Dim sweepAngle As Single=135.0F
Dim reca As New Rectangle(200,100)
g.FillPie(brush,rec1,startAngle,sweepAngle) '填充扇形
3.坐标变换
坐标变换是GDI+提供的一项重要功能。在画布上绘制图形之前,若做画布平移、缩放、旋转变换,则之后在画布上所绘制的图形均随画布而变换,可以获得很生动的效果。如画布旋转450后,在画布上的正方形在屏幕上呈现的是菱形。
(1)平移(TranslateTransform方法)
语法:
TranslateTransform(X轴方向偏移量,Y轴方向偏移量)
功能:
用指定的X轴方向和Y轴方向的偏移量进行偏移。若x,y为正值,则画布向右和向下平移;若x,y为负值,则画布向左和向上移动。
例:将原来的图形按X轴向右平移100像素,按Y轴向下平移150像素。
g.TranslateTransform(100,150)
(2)旋转(RotateTransform方法)
语法:
RotateTransform(旋转角度)
功能:
旋转变换是指相对坐标原点旋转指定的角度,旋转方向以顺时针为正。
例:使以后绘制的图形,皆旋转150。
g.RotateTransform(15)
(3)比例(ScaleTransform)
语法:
ScaleTransform(X轴比例,Y轴比例)
功能:比例变换是指用指定的X轴和Y轴的比例对图形进行变换,即设置画布的缩放比例。
例:使以后绘的图形,皆会宽度放大3倍,高度缩小一半。
g.ScaleTransform(3,0.5)
4.绘制图形的一般步骤
在创建一个Graphics对象后,就可以用Graphics类的方法在窗体上绘制基本图形了。通常,在VB.NET中绘制图形包括以下几点:
(1)使用颜色
颜色是绘图必要的因素,因此绘图前需要先定义颜色,颜色可以使用Color结构中自定义的颜色,也可以通过FromArgb()方法来创建RGB颜色。
(2)使用画笔
根据需要可对画笔的属性进行设置,例如Pen的Color属性,可以设置画笔的颜色,DashStyle属性可设置Pen的线条样式。
(3)使用画刷
创建画刷有多种方式,可以创建SolidBrush、HatchBrush、TextureBrush等,前面已详细说明了。
(4)使用Graphics类提供的函数给图
Graphics类提供的绘图方法包括以下几大类:线条、矩形、多边形、圆、椭圆、圆弧、贝济埃曲线、字符串、图标、图像。
(5)释放资源
释放程序中创建的Graphics、Pen、Brush等资源,应尽快释放,调用该对象的Dispose()方法即可。如果不调用Dispose方法,则系统自动回收这些资源,但释放资源的时间会滞后。
[知识扩展]
1. VB.NET的自定义数据类型--结构
(1)结构的定义
在VB.NET中,用户可自定义数据类型(User-Defined Tyepes,UDT),定义时使用关键字Structure,其语法如下:
Structure 结构名
Public| Dim| Private 类型成员
End Structure
在Structure内部声明类成员,可使用Public、Dim、Private。Structure内部的Dim和Public同义,都可以通过变量访问其成员数据。
例如:前面介绍的point结构定义。
Public Structure Point
Public x As Integer '获取或设置此 Point 的 x 坐标
Public y As Integer '获取或设置此 Point 的 y 坐标
Public ReadOnly Property IsEmpty As Boolean '获取一个值,该值指示此 Point 是否为空
……
End Structure
(2)结构与类的比较
VB.NET 统一了结构和类的语法,它们都支持大多数的相同功能,但结构和类之间也有重要的区别。
①结构和类的主要相同之处
l 两者都属于"容器"类型,表示它们可以包含其他类型作为成员。 两者都具有成员,成员可以包括构造函数、方法、属性、字段、常数、枚举、事件和事件处理程序。 都可实现接口。
l 都有共享的构造函数,有或没有参数。 两者都可以公开默认属性,只要该属性至少带有一个参数,都可以声明和引发事件,而且两者都可以声明委托。
②结构与类的主要不同之处
l 结构是值类型,而类是引用类型。结构是不可继承的;而类可以继承。
l 所有的结构成员都默认为 Public;类变量和常量默认为 Private,而其他的类成员默认为 Public。类成员的这一行为提供与 Visual Basic 6.0 默认值系统的兼容。
l 结构变量声明不能指定初始值、New 关键字或数组初始大小,类变量声明可以。
l 结构从不终止,所以公共语言运行库 (CLR) 从不在任何结构上调用 Finalize 方法,类可由垃圾回收器终止,当检测到没有剩下的活动引用时,垃圾回收器将在类上调用 Finalize。
l 结构不需要构造函数;而类需要。 结构仅当没有参数时可以有非共享的构造函数;类无论有没有参数都可以。
每一个结构都有不带参数的隐式公共构造函数。此构造函数将结构的所有数据成员初始化为默认值。不能重定义此行为。
2.GDI+(Graphic Device Interface)简介
VB.NET具有相当强大的图形图像功能,在对原有GDI技术进行改进后,形成了现在集成在VB.NET中的GDI+技术。Windows窗体可看作是一块画板,画笔、画刷等是绘画的工具,用户只有通过GDI+这个接口才可使用这些工具。
GDI+是图形设备接口,它负责在屏幕和打印机上显示信息,程序员可利用它来编写与设备无关的应用程序。GDI+是GDI的后续版本,它使程序开发人员不必考虑不同显卡之间的区别,可直接调Windows API函数绘制图形。
Windows API是Windows操作系统的应用程序接口,它提供了能操作Windows操作系统的底层函数,存放在系统的3个dll(动态链接库)文件中。其中GDI32.dll存放图形函数,Kernel.dll存放较底层的操作系统函数,User32.dll提供窗口管理函数。
GDI+由.NET类库中System.Drawing命名空间下的很多类组成,这些类包括在窗体上绘图的必需功能,可以在屏幕上完成对文本和位图的绘制,也可以控制字体、颜色、线条粗细、阴影、方向等因素,并把这些操作发送到显示卡上,确保在显示器上正确输出。
GDI+对GDI进行了重新封装,使之成为更直观的面向对象模型,此外GDI+比GDI提供了一些新的功能,在性能方面也作了改进,使之简单易用。
GDI+技术把打印机与屏幕看作是同样的输出设备,当要进行打印时,只需通知系统此时的输出设备是打印机,再调用与屏幕绘图时相同的函数即可。GDI+提供的主要命名空间如下:
System.Draw.Desin命名空间: 包括一些预定义的对话框、属性框等界面对象。
System.Draw.Drawing2D命名空间: 提供高级的二维和矢量图形功能。
System.Draw.Image命名空间: 提供图像处理的各种类。
System.Draw.Printing命名空间: 将图像输出到打印机或打印预览时使用的类。
System.Draw.Text命名空间:该命名空间中的类允许用户创建和使用多种字体。
7.2 图形的浏览
VB.NET不仅具有强大的图形绘制功能,而且还可以多种方式浏览图形,有很强的图像处理能力。
【案例7-2】 仿图形浏览器
此图像浏览器在案例6-1的基础上制作。其运行界面如图7-4所示。在左边的树型目录结构中选择文件夹;在右边的上方显示所选文件夹中的图像文件;双击某图像文件,则在右下方的显示该图像文件。
图7-5 图像浏览主界面
[技能目标]
1. 熟悉图形浏览器开发过程。
2. 进一步掌握控件PictureBox、TreeView、ListView控件的应用。
[操作要点与步骤]
1.建立一个新的Windows应用程序,命名为vbnet7-2。
2.在窗体中添加控件:一个TreeView控件显示计算机系统的树型目录结构,一个ListView 控件显示所选择文件夹中文件,一个PictureBox控件显示所选图像文件,一个StatusBar 控件用于显文件所在路径及有关信息。调整各控件大小及位置。
此案例可在案例6-1的基础上直接修改得到,即将其中的RichTextBox控件改换成PictureBox控件。
3.设置各控件的相关属性置,如表7-5 所示。
表7-5 控件属性设置
Form Form1 Text Vbnet7-2
PictureBox PictureBox1 SizeMode StretchImage
StatusBar StatusBar1 text StatusBar1
Filepath text 文件名及路径:
AutoSize contents
BorderStyle Raised
Filename text
AutoSize Spring
BorderStyle Sunken
在此仅给出ListView1 控件的DoubleClick事件代码,其他代码与案例6-1中相同。
Private Sub ListView1_DoubleClick(ByVal sender As Object,ByVal e As System.EventArgs) Handles_
ListView1.DoubleClick
Dim strFilePath As String ' 文件路径
Dim Mystream As StreamReader ' 定义读流对象
Dim strItemName As String ' 激活的文件名
Dim intLength,i As Integer
Dim strXName As String ' 文件扩展名
strItemName = ListView1.SelectedItems(0).Text
strCurrentfile = strItemName
intLength = strItemName.Length
strFilePath = strCurrentPath + "/" + strItemName ' 取得当前物理路径
' 下面的循环是判断文件类型
For i = intLength - 1 To 0 Step -1
If strItemName.Chars(i) = "." Then Exit For
Next
strXName = strItemName.Substring(i)
If strXName = ".jpg" Or strXName = ".JPG" Or strXName = ".bmp" Or _
strXName = ".BMP" Then
' 如果是jpg或bmp文件,则将此图形文件显示在PictureBox控件中
PictureBox1.Image = Image.FromFile(strFilePath)
Filenam.Text = strFilePath + strItemName.ToString()
End If
End Sub
代码编写完毕,按F5或工具栏上的运行按扭可调试运行程序。
[相关知识]
PictureBox控件主要用于加载图片,所支持的图形文件格式有位图(.bmp)、GIF格式(包括GIF动画及背景透空的静态图)、JPEG图形文件、矢量图形格式文件(.wmf)、或图标格式(.ico)的图形。PictureBox控件中显示的图片可以设计阶段加载,或在程序执行时再加载。其常用属性说明如表7-6。
设置图片源需要使用Image类的FromFile方法,也可利用属性窗口直接设置图片源文件。如果想要执行图片的另存为操作,可以使用Image类的Save方法并指定存储路径、名称以及格式。
PictureBox可以配合Dock或Anchor属性使用,如将Dock 属性设置为"Fill",PictureBox就会填充整个窗体,也会自动随着窗体的变化而改变大小。
属性 说明
BackGroundImage 设置PictureBox的背景图片
SizeMode 设置PictureBox与图片的尺寸关系,有Normal( 原图显示)、StretchImage(自动缩放图片)、AutoSize(自动缩放PictureBox)、CenterImage(图片居中)4个选项
【案例7-3】图形变换显示
此案例在原图形区显示未经变换的图形,单击界面中的翻转和镜像按钮,在变换后图形区显示相应变换后的图形。单击"退出"按钮结束程序运行。运行界面如图7-6所示。
[技能目标]
1. 理解图形变换的概念。
2. 掌握图形变换程序设计的思路和技巧。
[操作要点与步骤]
1.建立一个新的Windows应用程序,命名为vbnet7-3。
(a) 翻转效果图
(b)镜像效果图
图7-6 图像变换效果图
2.在窗体中添加控件:2个Label控件用于显示两个图形区,2个Panel控件用于显示原图和变换后图形,3个Button命令按钮控件用于控制图形变换方式和结束程序运行。调整各控件位置及大小。
3. 设置各控件属性,如表7-7所示。
表7-7 控件属性表
Form Form1 text Vbnet7-3
Label Label1 text 原图形
Label2 text 变换后图形
Panel Panel1 Location 29,48
BorderStyle Fixed3D
Panel2 Location 298,48
BorderStyle Fixed3D
Button Button2 Text 翻转
Button3 Text 镜像
Button4 Text 退出
4.编写代码。首先在Form1类中定义变量,如下所示。
Dim pic1,pic2 As Bitmap
Dim flag As Integer = 0 '用于标志选择哪种图形变换
(1)为Form1的Load事件编写代码,如下所示。
Private Sub Form1_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles MyBase.Load
Panel1.Height = Panel1.Width
Panel2.Width = Panel1.Width
Panel2.Height = Panel2.Width
Dim pic As Image = Image.FromFile("strawberry.jpg")
pic1 = New Bitmap(pic,Panel1.Width,Panel1.Height)
pic2 = New Bitmap(pic1)
End Sub
将图形文件放置在bin文件夹内,直接指定图形文件即可,当然也可放置在其他文件夹中,但必须指明文件夹。
(2)为Panel1的Paint事件编写代码,如下所示。
Private Sub Panel1_Paint1(ByVal sender As Object,ByVal e As System.Windows.Forms.PaintEventArgs)_
Handles Panel1.Paint
Dim g As Graphics = e.Graphics
g.DrawImage(pic1,0)
End Sub
(3)为Panel2 的Paint事件编写代码,如下所示。
Private Sub Panel2_Paint(ByVal sender As Object,ByVal e As System.Windows.Forms.PaintEventArgs)_
Handles Panel2.Paint
Dim g As Graphics = e.Graphics
Dim x As Integer = Panel2.Width
Dim col As Color = New Color
Select Case flag
Case 1
Dim pic3 As Bitmap
pic3 = New Bitmap(x,x)
Dim i,j As Integer
For i = 0 To x - 1
For j = 0 To x - 1
col = pic2.GetPixel(i,j)
pic3.SetPixel(i,x - 1 - j,col)
Next
Next
g.DrawImage(pic3,0)
pic2 = New Bitmap(pic3)
Case 2
Dim pic4 As Bitmap
pic4 = New Bitmap(x,j)
pic4.SetPixel(x - i - 1,j,col)
Next
Next
g.DrawImage(pic4,0)
pic2 = New Bitmap(pic4)
End Select
flag = 0
End Sub
(4)为Button2的click事件编写代码,如下所示。
Private Sub Button2_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)_
Handles Button2.Click
flag = 1
Panel2.Invalidate()
End Sub
(5)为Button3的click事件编写代码,如下所示。
Private Sub Button3_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)_
Handles Button3.Click
flag = 2
Panel2.Invalidate()
End Sub
(6)为Button4的click事件编写代码,如下所示。
Private Sub Button4_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)_
Handles Button4.Click
End
End Sub
至此程序编写完成,按F5或工具栏上的 运行按钮可运行程序。
[相关知识]
1. Bitmap
Bitmap类封装 GDI+ 位图,此位图由图形图像及其属性的像素数据组成。Bitmap 对象是用于处理由像素数据定义的图像的对象。
方法GetPixel:获取Bitmap对像中指定像素的颜色。
方法SetPixel:设置Bitmap 对象中指定像素的颜色。
2. Panel控件
Panel 是一个包含其他控件的控件(也称面板)。可以使用 Panel来对窗体界面上的控件进行适当的逻辑分组。例如一组单选钮组成的性别组和一组复选框组成的爱好组就可以用两个Panel来区分。与其他容器控件(如 GroupBox 控件)一样,如果 Panel 控件的 Enabled 属性设置为 false,则也会禁用包含在 Panel 中的控件。
默认情况下,Panel 控件在显示时没有任何边框。可以用 BorderStyle 属性提供标准或三维的边框,将窗体面板区与窗体上的其他区域区分开。因为 Panel 控件派生于 ScrollableControl 类,所以可以用 AutoScroll 属性来启用 Panel 控件中的滚动条。当 AutoScroll 属性设置为 true 时,使用所提供的滚动条可以滚动显示Panel 中(但不在其可视区域内)的所有控件。
Invalidate方法: 使控件的特定区域无效并向控件发送绘制消息。
Point To Screen方法:将指定工作区点的位置计算成屏幕坐标。
Panel 控件类似于 GroupBox 控件;但只有 Panel 控件可以有滚动条,而且只有 GroupBox 控件显示标题。
7.3 动画制作
应用基本的绘图命令和适当的绘图模式,可以制作各种动画效果。另外,利用时间变化更换不同的图像图序或移动图形位置也可以产生动画效果。
【案例7-4】小向导
这个案例使用Graphics对象的FillPie命令绘制出缺口大小不同的扇形图,再利用时间事件来控制扇形图位置的变化,产生类似小向导动画的视觉效果。运行界面如图7-7所示。
(a)
(b)
图7-7 小向导运行界面
[技能目标]
1. 理解简单动画开发过程。
2. 熟悉利用时间变化和绘图命令设计动画程序的技巧。
[操作要点与步骤]
1.建立一个新的Windows应用程序,命名为vbnet7-4。
2.在窗体中添加控件:添加一个Label标签控件,用于显示小向导的标题;添加一个Timer时间控件,用于控制扇形图形位置的变化速度;添加一个Button命令按钮,用于停止程序的运行。调整窗体及控件的大小与位置。
3.设置控件属性,其值如表7-8所示。
表7-8控件属性设置
Form Form1 text Vbnet7-4
label Label1 text 小向导(动画演示)
Timer Timer1 Enabled True
Interval 150
Button Button1 text 停止演示
Timer1的Enabled属性值为True,表示启用Elapsed事件;Interval属性值为150,单位是毫秒,表示Elapsed事件的频率,值越小,变化得越快,反之越慢。
4.编写代码。
(1)首先在Form1类中定义变量,代码如下。
Dim sw,status As Integer
Dim x,r As Integer
Dim rx,ry,rsw As Integer
Dim ra(2) As Integer
Dim rb(2) As Integer
Dim g2 As Graphics
(2)为Form1的Load事件编写代码,设置初始值,代码如下所示。
Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load
g2 = Me.CreateGraphics
x = 300 :y = 65 :r = 50
ra(0) = 135 '第一个图的起始角度
rb(0) = -270 '第一个图的结束角度
ra(1) = 170 '第二个图的起始角度
rb(1) = -340 '第二个图的结束角度
sw = 0
status = 0
Timer1.Enabled = True
End Sub
(3)为Timer控件的Tick事件编写代码,在不同的时间间隔里于不同位置绘制不同缺口的扇形,并且一直从右往左循环运动直到停止运行。代码如下所示。
Private Sub Timer1_Tick(ByVal sender As Object,ByVal e As System.EventArgs) Handles Timer1.Tick
g2.Clear(Color.White)
g2.FillPie(Brushes.Blue,r,ra(sw),rb(sw))
rx = x : ry = y : rsw = sw
sw = 1 - sw
x = x - 10 '变化坐标位置
If x < 10 Then x = 300
End Sub
(4)为Button1控件编写代码,当单击此按钮时结束程序运行。代码如下。
Private Sub Button1_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)_
Handles Button1.Click
End
End Sub
End Class
至此,程序编写完成,按F5或工具栏中的运行按钮即可执行程序。
[相关知识]
VB.NET不仅有强大的绘制图形功能,能够利用Graphics类基本绘图命令制作出丰富多彩的静态的图形,而且能让静止的图形随着时间变化发生位置与形状的改变,产生形象生动的动画效果。
动画制作中,时间变化是由Timer控件来实现的,其中Interval属性值的大小与动画运行的速度相关,间隔越小,速度越快。
【案例7-5】 移动动画
移动动画是简单的动画技巧,利用Graphics对象的DrawImage方法可以显示图像文件,配合Timer时间的变化,就可以改变图像坐标,以产生移动动画效果。
[案例说明]
本案例使用图像文件的运动产生动画效果。程序运行时,花的图案作为背景,小鸟图案从右到左移动,反复运动,直至停止。运行界面如图7-8所示。
(a)
(b)图7-8 移动动画运行界面
[技能目标]
1. 熟悉简单动画开发过程。
2. 熟悉利用图形文件设计动画程序的技巧。
[操作要点与步骤]
1.建立一个新的Windows应用程序,命名为vbnet7-5。
2.在窗体中添加控件:添加一个Label控件用于显示"移动动画"标题;添加一个 PictureBox 控件用于显示图形文件;添加一个Timer时间控件用于设置动画频率。调整窗体各控件的大小及位置。
表7-9 属性设置
Form Form1 Text Vbnet7-5
Label Label1 Text 移动动画
PictureBox PictureBox1 Locked True
BorderStyle Fixed3A
SizeMode StretchImage
Timer Timer1 Enabled True
Interval 200
4. 编写代码。
(1)首先在Form1类中定义如下变量并赋初始值。
Dim px,py As Integer
Dim g2 As Graphics
Dim image1 As New Bitmap("flowers.gif")
Dim image2 As New Bitmap("bird.gif")
(2)为Form1的Load事件编写代码。
Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load
g2 = PictureBox1.CreateGraphics
px = 300
py = 40
End Sub
(3)为Timer1控件的Tick事件编写代码。
Private Sub Timer1_Tick(ByVal sender As Object,ByVal e As System.EventArgs) Handles Timer1.Tick
g2.DrawImage(image1,0)
px= 10
g2.DrawImage(image2,New Point(px,py))
If px < 5 Then px = 300
End Sub
至此代码编写完成,按F5 或工具栏上的运行按钮运行程序。
[相关知识]
VB.NET中可使用Graphics类的DrawImage方法显示图形文件,在不同时间间隔里于不同的位置显示同一图形文件会产生视觉上的动画效果。DrawImage方法可指定目的绘图区,也可指定源图片的显示范围,具备自动缩放功能,会自动将图片放大或缩小以填满指定的整个区域,主要有以下几种使用方式。
DrawImage(Image对象,y)
DrawImage(Image对象,Point结构)
DrawImage(Image对象,目的Rectangle结构)
DrawImage(Image对象,源Rectangle结构,图形单位)
DrawImage(Image对象,目的Rectangle结构,图形单位)
练习园地7
一、基础题
1.简述GDI+的内容及其包含的命名空间。
2.如何理解GDI+的"与设备无关性"?
3.用Graphics类绘图一般有哪些步骤?
4.用Graphics 类能绘制哪些基本图形?
5.在GDI+中如何实现坐标变换?
二、实战题
1.用Graphics类提供的方法在窗体上绘制所有的基本图形。
2.完成本章所有案例的制作与调试。
3.编程完成图7-9中调色盘界面,其功能是:调整左边的四个滑块值,则右边显示相应颜色及ARGB值。
图7-9
4.以Timer控件配合PictureBox控件设计一个可以定时切换不同图形的动画效果。
5.使用Timer对象,设计一个窗体中有不断移动的球(或其他图形),可以单击按钮让图形加速及减速移动。
三、挑战题
1、利用画布的各种变换设置,完成图7-10所示界面的程序设计。
(a)缩放界面
(b)平移界面
(c) 旋转界面
图7-10