图形基础
1.笔和画刷
1)Pen类
应用Pen类来创建Pen对象,在创建过程中可以指明颜色、线宽、样式等属性。Pen类共有四个构造函数。
- Public Pen(color);
- Public Pen(color,float);
- Public Pen(brush);
- Public Pen(brush,float);
Pen类除提供了四个不同的构造函数外,还提供了如下一系列属性,以便于控制实例对象的行为状态
- Alignment ---- 获得或设置Pen对象的排列
- Brush ---- 获得或设置初始化Pen对象时的brush对象
- Color ---- 获得或设置Pen对象的颜色
- DashStyle ---- 获得或设置Pen对象的线样式
- Width ---- 获得或设置Pen对象的宽度
2)Brush类
画刷应用于利用颜色、模板和图像充填各种形状的图形(如矩形,椭圆形等)。brush类是一个抽象的基类,因而不能被实例化,为了创建Brush对象,必须用Brush类的派生类
其派生类如下:
- SolidBrush ---- 定义了用一种单色填充图像的画刷
- TextureBrush ---- 定义了用一个位图填充图像的话术
- HatchBrush ---- 定义了带有阴影样式,前景色和背景色的矩形画刷
- LinearGradientBrush ---- 封装了一个画笔。该画笔可以绘制两种颜色渐变的图形,其中一种颜色以指定的角度逐渐过渡到第二种颜色(角度0表示从左到右过渡,90表示从上到下过渡)
- PathGradientBrush ---- 封装了一个画刷,该画刷可以创建精细的阴影效果,其中阴影从路径的中心趋向路径的边界
2.基本图形形状
1)点
在GDI+中Point类有两个不同的构造函数:Point和PointF。Point构造函数使用一对整形的X、Y坐标数值来定义二维平面上的点。point构造函数具有三个重载的方法,下面的代码段,显示了如何创建一个Point对象
point p1 = new Point(); //默认的坐标值(0,0)
point p2 = new Point(new Size(10,100));
point p2 = new Point(20,200);
PointF用浮点值替代了整型值,PointF构造函数仅有 PointF()和PointF(float,float)两种重载的方法。
Point对象具有IsEmpty、X属性和Y属性,IsEmpty的意思是该点的X值和Y值均为0
2)直线和曲线
直线和曲线都包括在Line对象中,Line对象通过调用DrawLine方法或DrawCurve方法分别绘制直线或曲线。
//绘制一条直线
Graphics g = new Graphics();
g.DrawLine(Pen.Black,x1,y1,x2,y2);
g.DrawLine(Pens.Black,point1,point2);
坐标值或点的值既可以是整型的,也可以是浮点型的
DrawCurve方法是通过将一个点数组中的每一个点平滑地连接起来实现曲线绘制的。
Graphics g = new Graphics();
g.DrawCurve(Pens.Black,new Point[]);
DrawLine和DrawCurve方法仅能直接绘制实线的直线和曲线,但线段的样式是多种多样的,如点线、带起始端的线段等,要实现这些特殊的线段样式必须依靠Pen类中的样式属性。
Graphics g = e.Graphics;
Pen p1 = new Pen(Color.Blue, 10);
g.DrawLine(p1, 20, 20, 330, 20);
Pen p2 = new Pen(Color.Red, 10);
float[] Pts = { 3, 1, 2, 5 };
p2.DashStyle = DashStyle.Dash;
p2.DashPattern = Pts;
p2.DashCap = DashCap.Triangle;
p2.StartCap = LineCap.Round;
p2.EndCap = LineCap.ArrowAnchor;
g.DrawLine(p2, 20, 50, 330, 50);
Pen p3 = new Pen(Color.Yellow, 10);
Single[] lines = { 0.0f, 0.1f, 0.9f, 1.0f };
p3 = new Pen(Color.Yellow, 20);
p3.CompoundArray = lines;
g.DrawLine(p3, 20, 80, 330, 80);
p3.Dispose();
p3 = new Pen(Color.Gray, 10);
p3.DashStyle = DashStyle.Dot;
g.DrawLine(p3, 20, 110, 330, 110);
p3.Dispose();
p3 = new Pen(Color.Black, 10);
p3.DashStyle = DashStyle.DashDotDot;
p3.StartCap = LineCap.ArrowAnchor;
p3.EndCap = LineCap.ArrowAnchor;
g.DrawLine(p3, 20, 140, 330, 140);
p3.Dispose();
p3 = new Pen(Color.DarkGreen, 10);
p3.DashStyle = DashStyle.Solid;
p3.EndCap = LineCap.ArrowAnchor;
g.DrawLine(p3, 20, 170, 330, 170);
p3.Dispose();
p3 = new Pen(Color.SkyBlue, 3);
Point[] point = new Point[]
{
new Point(10,220),
new Point(200,200),
new Point(330,230),
new Point(110,250),
};
g.DrawCurve(p3, point);
if (p1 != null)
p1.Dispose();
if (p2 != null)
p2.Dispose();
if (p3 != null)
p3.Dispose();
3)矩形、椭圆形和圆弧形
在GDI+中,利用Rectangle和RectangleF两个构造函数来定义矩形对象,这两者的区别仅在于Rectangle构造函数利用整型坐标值,RectangleF构造函数利用浮点坐标值
椭圆形、圆弧形都是绘制在矩形范围内的。
函数名 | 功能描述 |
---|---|
DrawAre | 画一段圆弧 |
DrawEllipse | 画一个椭圆 |
DrawRectangle | 绘制矩形 |
FillEllipse | 填充椭圆 |
FillRectangle | 填充矩形 |
Graphics g = e.Graphics;
//椭圆矩形和斜度画刷
Rectangle drawArea1 = new Rectangle(5, 35, 30, 100);
LinearGradientBrush linearBrush = new LinearGradientBrush
(drawArea1, Color.Blue, Color.Yellow, LinearGradientMode.ForwardDiagonal);
//画用蓝黄斜度填充的椭圆
g.FillEllipse(linearBrush, 5, 30, 65, 100);
//红外框矩形的笔和区位
Pen thickRedPen = new Pen(Color.Red, 10);
Rectangle drawArea2 = new Rectangle(80, 30, 65, 100);
//画红色的厚矩形外框
g.DrawRectangle(thickRedPen, drawArea2);
//绘图结构
Bitmap textureBitmap = new Bitmap(10, 10);
//取得位图图像
Graphics g2 = Graphics.FromImage(textureBitmap);
//整个程序使用的画刷和笔
SolidBrush solidColorBrush = new SolidBrush(Color.Red);
Pen coloredPen = new Pen(solidColorBrush);
//用黄色填充结构绘图
solidColorBrush.Color = Color.Yellow;
g2.FillRectangle(solidColorBrush, 0, 0, 10, 10);
//用结构绘图画小的黑色矩形
coloredPen.Color = Color.Black;
g2.DrawRectangle(coloredPen, 1, 1, 6, 6);
//用结构绘图画小的蓝色矩形
solidColorBrush.Color = Color.Blue;
g2.FillRectangle(solidColorBrush, 1, 1, 3, 3);
//用结构绘图画小的红色正方形
solidColorBrush.Color = Color.Red;
g2.FillRectangle(solidColorBrush, 4, 4, 3, 3);
//创建结构画刷并显示结构矩形
TextureBrush textureBrush = new TextureBrush(textureBitmap);
g.FillRectangle(textureBrush, 155, 30, 75, 100);
//画白色饼状狐仙
coloredPen.Color = Color.White;
coloredPen.Width = 6;
g.DrawPie(coloredPen, 240, 30, 75, 100, 0, 270);
//画绿线和黄线
coloredPen.Color = Color.Green;
coloredPen.Width = 5;
g.DrawLine(coloredPen, 390, 30, 320, 150);
//画一条圆形黄色破折线
coloredPen.Color = Color.Yellow;
coloredPen.DashCap = DashCap.Round;
coloredPen.DashStyle = DashStyle.Dash;
g.DrawLine(coloredPen, 320, 30, 395, 150);
//画一条弧线
coloredPen.Color = Color.Pink;
coloredPen.Width = 2;
g.DrawArc(coloredPen, 330, 30, 200, 100, -60, 180);
4)多边形
DrawPolygon方法用于绘制由点数组(数组元素的值为一系列的坐标值)定义的多边形。数组中的每一对两个连续的点代表了多边形的一条边,另外,如果数组的最后一个点和第一个点不重合,则这两点代表了多边形的最后一条边。FillPolygen方法用于填充多边形内部的方式绘制多边形
3.颜色
GDI+中的许多绘图操作都涉及颜色。在绘制线条或矩形等时,都需要指定使用了什么颜色。在GDI+中,颜色封装在Color结构中,Color结构包含了大约150个属性,提供了大量预置颜色,应用Color结构创建Color对象是相当简单的。
C#中有以下几种不同的创建颜色的方法:
- ARGN(透明度、红、绿、蓝)颜色值,每个值的范围在0~255之间;
- 预定义的 .Net颜色名
- 系统环境预定义的颜色名
- Win32颜色代码
- OLE颜色代码
- 颜色选择对话框
//用ARGB值创建颜色
int alpha = 100;
int red = 255;
int green = 200;
int blue = 166;
this.BackColor = Color.FromARGB(alpha,red,green,blue);
//用 .Net 颜色名创建颜色
this.BackColor = Color.lightyellow;
//用系统环境颜色设置创建颜色
this.BackColor = SystemColor.Highlightext;
//用HTML颜色代码创建颜色
this.BackColor = ColorTranslator.FromHTML(*Red);
//用Win32颜色代码创建颜色
this.Backcolor = colorTranslator.FromWin32(OxFF00);
//用OLE颜色代码创建颜色
this.BackColor = ColorTranslator.FromOle(OxFF00);
//用颜色选择对话框创建颜色
ColorDialog cdl = new ColorDialog();
cdl.ShowDialog();
this.BackColor = cdl.color;
表示颜色的另一种途径是把颜色分解为三种组件,色调、饱和度、亮度。Color结构包含完成分解颜色的使用方法:GetBrightness(),GetHue(),GetSaturation(),ToArgb()
另外,C#提供了一个KnowColors枚举,包含了系统预定义的颜色名,如果欲在应用程序中列出有效的系统颜色名,利用它是最有效的方法。
String[] colorName = Enum.GetNames(typeOf(knownColor));
绘制星条旗
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.ResizeRedraw, true);
this.Width = 500;
this.Height = 310;
this.BackColor = Color.LightGreen;
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
DrawFlag(g, 20, 20, this.Width - 50);
}
private void DrawFlag(Graphics g,float x0,float y0,float width)
{
SolidBrush whiteBrush = new SolidBrush(Color.White);
SolidBrush blueBrush = new SolidBrush(Color.FromArgb(0, 0, 128));
SolidBrush redBrush = new SolidBrush(Color.Red);
float height = 10 * width / 19;
//画白色矩形背景
g.FillRectangle(whiteBrush, x0, y0, width, height);
//画7条红色条纹
for(int i = 0; i < 7; i++)
{
g.FillRectangle(redBrush, x0, y0 + 2 * i * height / 13, width, height / 13);
}
//画蓝色方框
RectangleF blueBox = new RectangleF(x0, y0, 2 * width / 5, 7 * height / 13);
g.FillRectangle(blueBrush, blueBox);
//把蓝色方框内画50颗星
float offset = blueBox.Width / 40;
float dx = (blueBox.Width - 2 * offset) / 11;
float dy = (blueBox.Height - 2 * offset) / 9;
for(int j = 0; j < 9; j++)
{
float yc = y0 + offset + j * dy + dy / 2;
for(int i = 0; i < 11; i++)
{
float xc = x0 + offset + i * dx + dx / 2;
if ((i + j) % 2 == 0)
{
DrawStar(g, this.Width / 55, xc, yc);
}
}
}
whiteBrush.Dispose();
blueBrush.Dispose();
redBrush.Dispose();
}
private void DrawStar(Graphics g,float r,float xc,float yc)
{
//r决定星的大小
//xc,yc决定星的位置
float sin36 = (float)Math.Sin(36.0 * Math.PI / 180.0);
float sin72 = (float)Math.Sin(72.0 * Math.PI / 180.0);
float cos36 = (float)Math.Cos(36.0 * Math.PI / 180.0);
float cos72 = (float)Math.Cos(72.0 * Math.PI / 180.0);
float r1 = r * cos72 / cos36;
//填充星
PointF[] pts = new PointF[10];
pts[0] = new PointF(xc, yc - r);
pts[1] = new PointF(xc + r1 * sin36, yc - r1 * cos36);
pts[2] = new PointF(xc+r*sin72, yc - r*cos72);
pts[3] = new PointF(xc+r1*sin72, yc +r1*cos72);
pts[4] = new PointF(xc+r*sin36, yc +r*cos36);
pts[5] = new PointF(xc, yc + r1);
pts[6] = new PointF(xc - r*sin36, yc + r*cos36);
pts[7] = new PointF(xc-r1*sin72, yc + r*cos72);
pts[8] = new PointF(xc-r*sin72, yc - r*cos72);
pts[9] = new PointF(xc-r1*sin36, yc - r1*cos36);
g.FillPolygon(Brushes.White, pts);
}
4.双倍缓存
所谓双倍缓存就是在缓存中创建一个高度和宽度与客户工作区大小相同的位图。在位图中绘制完成整个图形,再把它绘制到屏幕上,从而提高应用程序的性能
protected override void OnPaint(PaintEventArgs e)
{
Graphics displayGraphics = e.Graphics;
Random r = new Random();
//定义一个大小与客户区大小相同的位图
Image i = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
//从位图得到一个图形对象
Graphics g = Graphics.FromImage(i);
g.FillRectangle(Brushes.White, ClientRectangle);
for(int x = 0; x < ClientRectangle.Width; x++)
{
for(int y = 0; y < ClientRectangle.Height; y += 10)
{
Color c = Color.FromArgb(r.Next(255), r.Next(255), r.Next(255));
Pen p = new Pen(c, 1);
g.DrawLine(p, new Point(0, 0), new Point(x, y));
p.Dispose();
}
}
//在屏幕上绘制图形
displayGraphics.DrawImage(i, ClientRectangle);
i.Dispose();
}
Color c = Color.FromArgb(r.Next(255), r.Next(255), r.Next(255));
Pen p = new Pen(c, 1);
g.DrawLine(p, new Point(0, 0), new Point(x, y));
p.Dispose();
}
}
//在屏幕上绘制图形
displayGraphics.DrawImage(i, ClientRectangle);
i.Dispose();
}