创建和使用Graphics对象
用计算机语言编写成的程序是对相关事物和关系的高度抽象和概括。为了更好地理解这一节的内容,我们从绘画这件事情说起。我们的画,可以绘在纸上,布上,墙壁上,木板上,或者电脑屏幕上。用计算机语言来描述绘画这件事情的时候,就要进行抽象,这些纸、布、墙壁、木板、电脑屏幕可以全部抽象成一个表面,即一个可以绘图的表面。
GDI+中有绘图表面的概念,在这里,绘图表面可以是窗体、控件、打印机、预览或者图像。当指定绘图表面是图片框以后,绘图行为将在图片框上发生,而不会画到窗体上去。指起绘图表面是窗体时,绘图行为就在窗体上发生,也不会画在图片框上。但问题是,谁来指定绘图表面呢?想起一个笑话:老鼠们开会,议题是如何对付猫。有鼠提议,给猫脖子上挂个铃铛不就得了。提议近于完美,但问题是谁去给猫脖子上挂铃铛呢?
所以由谁来指定是问题的关键。
,这里是由Graphics.象来指定\"就像GDI中的设备上下文一样,Graphics象与特定的窗口相关联,指定绘图表面。
虽然把Graphics对象与上面的笑话联系在一起不太恰当,但关于谁来指定的问题的确太重要了。所以,这个(Gjrap cs对象太重要了,有人甚至说,术是最重要的。但本人,为如果把,Graphics对象比做纸的话,那还得有笔有墨这画才画得成。说哪个最重要就像讨论先有蛋还是先有鸡一样,不是我们研究的范畴。但不管哪个最重要,用GDI+进行具体的绘图工作以前,必须创建一个Graphics对象的实例却是千真万确的事实。
根据绘图表面的不同,有不同的创建Graphics对象实例的方法。当指定绘图表面为窗体时,下面的代码介绍了创建Graphics对象实例的两种方法。创建实例以后,对于该实例所做的任何绘图行为都作用在窗体上。
【VB.NET】
Public Class Form1
Inherits System.Windows.Forms.Form
'…
Protected Overrides Sub OnPaint(ByVal text-blue-400">e As PaintEventArgs)
Dim g As Graphics =text-blue-400">e.Graphics
'…
End Sub
Private Sub Button1_Click(ByVal sender As System.Object,_
ByVal text-blue-400">e As System.EventArgs) Handles Button1.text-blue-400">Click
Dim g As Graphics = Me.CreateGraphics()
'…
End Sub
End Class
【VC#.NET】
namespace Graph
{
public class Forml : System.Windows.Forms.Form
{
//…
protected override void OnPaint(PaintEventArgs e)
{
Graphics g= e.Graphics;
//…
}
private void button1_Click(object sender, EventArgs e)
{
Graphics g= this.CreateGraphics();
//…
}
}
}
第1种方法假设当前过程是绘制窗体的OnPaint方法,则可以直接从该方法的参数e中获得 raphic对象的实例;第和方法假设通过单击一个命令按钮来实现在窗体上绘图,此时调用Form1类的CreateGraphics方法创建Graphics对象实例。
如果指定绘图表面为控件,如图后框,则必须通过调用该控件的CreateGraphics方法来个建Graphics对象实 。下面的语句个建止片框控Pictre:Box1(rictre:Box)的G'raphics欢象实例。
【VB.NET)】
Dim g As Graphics = Picture Box1.CreateGraphics()
(VC#.NET】
Graphics g= pictureBox1.CreateGraphics();
创建Graphics对象的实例以后,就有了画布,但还要有笔和墨。在GDI+中,代表笔的Pen 对象和代表墨的Color对象是独立于代表纸的Graphics对象的,将在后面的小节中进行介绍。但关于Graphics对象的内容还远远没完。试想,我们讲书法要讲究章法,绘画要讲究构图,其实就隐含了坐标参照系的概念;写生素描要涉及到比例问题;用计算机绘图,还要提供组成任何几何图形所需要的基本图形元素如直线段、椭圆、椭圆弧、曲线、区域、文本等的绘制方法,这些都由Graphics对象提供。表3-1中示出了Graphics对象的部分属性,表3-2中示出了Graphics对象的部分方法。表中的内容将在后续章节中陆续用到,届时再进行详细说明。
表3-1至表1-3列出了Graphics对象的部分属性和方法。
下面举一个例子,介绍Graphics.象的创建和使用。该示例在窗体上放置一个图片框PictureBox1(pictureBox1)和两个命令按钮 Button1(button1)和 Button2(button2),要求重绘窗体时在图片框周围绘一个红色矩形:单击两个命令按钮时分别在窗体和图片框上绘制蓝色椭圆。本例用到了Pen对象、Brushes对象和Color对象。这里暂不做详细介绍,可参见后续章节的内容。
【VB.NET】
Protected Overrides Sub OnPaint(ByVal text-blue-400">e As PaintEventArgs)
Dim g As Graphics = text-blue-400">e.Graphics
Dim x As Single,y As Single
Dim w As Single,h As Single
With PictureBox1
x=.Left-2
y=.Top -2
W=.Width+4
h=.Height+4
End With
Dim pen As New Pen(Color.Red, 2)
g.DrawRectangle(pen,x,y, w,h)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal text-blue-400">e As System.EventArgs) Handles Button1.text-blue-400">Click
Dim g As Graphics = Me.CreateGraphics()
g.FillEllipse(Brushes.Blue, 10, 20, 50,100)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object,_
ByVal text-blue-400">e As System.EventArgs) Handles Button2.text-blue-400">Click
Dim g As Graphics = PictureBox .CreateGraphics()
g.Filllipse(Brushes.Blue, 10, 20, 50,100)
End Sub
【VC#.NET】
protected override void OnPaint(PaintEventArgs e)
{
Graphics g=e.Graphics;
float x, y,w,h;
x= pictureBox1.Left- 2;
y= pictureBox1.Top - 2;
w= pictureBox1.Width +4;
h = pictureBox1.Height +4;
Pen pen=new Pen(Color.Red, 2);
g.DrawRectangle(pen,x,y, w,h);
}
private void button1_Click(object sender, EventArgs e)
{
Graphics g= this.CreateGraphics();
g.Fillipse(Brushes.Blue, 10, 20, 50, 100);
}
private void button2_Click_1(object sender, EventArgs e)
{
Graphics g= pictureBox1.CreateGraphics();
g.FillElipse(Brushes.Blue, 10, 20, 50, 100);
}
运行程序,单击两个命令按钮以后窗体显示结果如图3-1所示。
图3-1创建和使用Graphics对象
Paint事件和OnPaint方法
上一节的例子中我们用到了OnPaint方法,它重写基类的OnPaint方法,用于绘制窗体。在VB6.0中,绘制窗体用的是窗体的Paint事件,每次要求绘制窗体时触发该事件。NET中绘制窗体也可以用Paint事件。如:
【VB.NET】
Private Sub Form1_Paint(ByVal sender As Object,_
ByVal text-blue-400">e As PaintEventArgs) Handles MyBase.Paint
Dim g As Graphics = text-blue-400">e.Graphics
g.DrawEllipse(Pens.Blue, 50, 50,100, 100)
End Sub
【VC#.NET】
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g=e.Graphics;
g.DrawEllipse(Pens.Blue,50,50,100,100);
}
这样,实现绘制窗体的任务就有两种方法供我们选择,但两种方法是有差别的。用Paint事件绘制窗体时,会调用基类的OnPaint方法,而用重写的OnPaint方法绘制窗体时则不需要调用基类的OnPaint方法。所以,前者的消耗要大一些。