GDI+学习笔记
Graphics 对象(代表设备上下文) 是唯一在绘图操作之间持续存在的对象。
一个设计良好的使用 GDI+ 的应用程序将需要在幕后做很多额外的工作,即它必须确保绘图有效地进行,并且在需要时更新屏幕,而不会发生任何不必要的绘图(这一点很重要,因为大多数绘图工作都会对应用程序造成很大的性能影响)。
GDI+ 基类中主要命名空间:
命名空间 | 说明 |
System.Drawing | 大多数类、结构、枚举和委托。涉及绘图的基本功能。 |
System.Drawing.Drawing2D | 更专业的课程等等。在屏幕上绘图时提供更高级的效果。 |
System.Drawing.Imaging | 帮助操作图像(位图、GIF 文件等)的各种类 |
System.Drawing.Printing | 当专门将打印机或打印预览窗口定位为输出“设备”时提供帮助的类。 |
System.Drawing.Design | 一些预定义的对话框、属性表和其他与延长用户界面设计时间有关的用户界面元素。 |
System.Drawing.Text | 对字体和字体系列执行更高级操作的类。 |
互换使用绘图和绘画这两个术语来描述在屏幕或其他显示设备上显示某些项目的过程。
绘图原理
设备上下文和图形对象
(客户区窗口的部分是窗口中通常用于绘图的部分——这通常意味着排除边框的窗口;
设备上下文始终知道您的窗口在哪里,并且能够自动执行此转换。这意味着您可以只要求设备上下文在窗口内的某个位置绘制一个项目,而无需担心应用程序窗口当前位于屏幕上的位置。
大多数绘图都是通过调用 Graphics 实例上的方法来完成的。事实上,由于 System.Drawing.Graphics 类是负责实际处理大多数绘图操作的类,因此在 GDI+ 中几乎没有什么不涉及 Graphics 实例的地方。了解如何操作该对象是了解如何使用 GDI+ 绘制到显示设备的关键。
使用 Graphics 的三种方式:
1. _Paint 事件
private void BaseTestForm_Paint(object sender, PaintEventArgs e) {//需要重绘时自动执行 //Graphics dc = e.Graphics; //Pen bluepen = new Pen(Color.Blue, 3); //dc.DrawRectangle(bluepen, 200, 300, 50, 50); //Pen redPen = new Pen(Color.Red, 2); //dc.DrawEllipse(redPen, 20, 500, 80, 60); }
2. 重载 OnPaint
protected override void OnPaint(PaintEventArgs e) {//重载绘图方法,窗体在需要重绘时,自动调用此方法 Graphics dc = e.Graphics; if (e.ClipRectangle.Bottom < 132 && e.ClipRectangle.Right < 200) {//剪切需要重新绘制的区域 Pen bluepen = new Pen(Color.Blue, 3); dc.DrawRectangle(bluepen, 0, 0, 50, 50); Pen redPen = new Pen(Color.Red, 2); dc.DrawEllipse(redPen, 0, 50, 80, 60); } base.OnPaint(e);//触发 BaseTestForm_Paint 事件,如果不执行此方法,Paint事件将不会执行 }
3. 手动绘制,窗体需要重绘时,不会自动绘制
private void BaseTestForm_Paint(object sender, PaintEventArgs e) {//需要重绘时自动执行 Graphics dc = e.Graphics; Pen bluepen = new Pen(Color.Blue, 3); dc.DrawRectangle(bluepen, 200, 300, 50, 50); Pen redPen = new Pen(Color.Red, 2); dc.DrawEllipse(redPen, 20, 500, 80, 60); }
测量坐标和面积
坐标或区域
Struct | 主要属性 |
Point,PointF | X,Y |
Size,SizeF | Width,Height |
Rectangle,RectangleF | Left,Right,Top,Bottom,Width,Height,X,Y,Location,Size |
三种不同的坐标系:世界坐标、页面坐标和设备坐标
当我们谈论某物在哪里时,使用 Point “点”;当我们谈论某物有多大时,使用 Size “大小”
关于调试的注意事项
设置条件,将断点设置在条件满足时触发
protected override void OnPaint( PaintEventArgs e ) { // Condition() evaluates to true when we want to break if ( Condition() == true) { int ii = 0; // <-- SET BREAKPOINT HERE!!! }
绘制可滚动窗口
public partial class BigShapesForm : Form { public BigShapesForm() { InitializeComponent(); this.components=new System.ComponentModel.Container(); this.Size = new System.Drawing.Size(300, 300); this.Text = "Scroll Shapes"; this.BackColor = Color.White; //滚动条,即绘制设备大小 this.AutoScrollMinSize = new System.Drawing.Size(250, 350); } Point rectangleTopLeft= new Point(0,0); Size rectangleSize= new Size(200,200); Point ellipseTopLeft= new Point(5,200); Size ellipseSize = new Size(200, 150); //将 Pen 对象转换为成员字段 - 这比每次我们需要绘制任何内容时创建一个新 Pen 更有效 Pen bluePen = new Pen(Color.Blue, 3); Pen redPen=new Pen(Color.Red, 2); protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; //g.Clear(BackColor); //翻译转换。它的工作原理是向它传递水平和垂直坐标, //这些坐标表示客户区域的左上角相对于文档左上角的位置(我们的 AutoScrollPosition 属性) //通过滚动条的位置,移动坐标原点,进行坐标转换 g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y); Size scrollOffset = new Size(this.AutoScrollPosition); if (e.ClipRectangle.Top + scrollOffset.Width < 350 || e.ClipRectangle.Left + scrollOffset.Height < 250) { Rectangle rectangleArea = new Rectangle(rectangleTopLeft, rectangleSize); Rectangle ellipseArea = new Rectangle(ellipseTopLeft, ellipseSize); g.DrawRectangle(bluePen, rectangleArea); g.DrawEllipse(redPen, ellipseArea); } base.OnPaint(e); } private void BigShapesForm_Load(object sender, EventArgs e) { } }
颜色
红-绿-蓝 (RGB) 值
Color RedColor = Color.FromArgb (255,0,0); this.BackColor = Color.White;
钢笔和画笔
Pen:告诉图形实例如何绘制线条。
Brush:如何填充区域。
单色填充画笔:
Brush solidBeigeBrush = new SolidBrush(Color.Beige); Brush solidFunnyOrangyBrownBrush = new SolidBrush(Color.FromArgb(255,155,100));
Brush solidAzureBrush = Brushes.Azure; Brush solidChocolateBrush = Brushes.Chocolate;
绘制图案来填充区域
位于 Drawing2D 命名空间中,由类表示System.Drawing.Drawing2D.HatchBrush
Brush crossBrush = new HatchBrush(HatchStyle.Cross, Color.Azure); // background color of CrossBrush is black Brush brickBrush = new HatchBrush(HatchStyle.DiagonalBrick, Color.DarkGoldenrod, Color.Cyan);
GDI+ 添加了几种新的画笔样式:
- System.Drawing.Drawing2D.LinearGradientBrush 使用随屏幕变化的颜色填充区域。
- System.Drawing.Drawing2D.PathGradientBrush 类似,但在本例中,颜色沿着要填充区域周围的路径变化。
钢笔
Brush brickBrush = new HatchBrush(HatchStyle.DiagonalBrick, Color.DarkGoldenrod, Color.Cyan); Pen solidBluePen = new Pen(Color.FromArgb(0,0,255)); Pen solidWideBluePen = new Pen(Color.Blue, 4); Pen brickPen = new Pen(BrickBrush); Pen brickWidePen = new Pen(BrickBrush, 10);
Pen SolidYellowPen = Pens.Yellow;
绘制形状和线条
System.Drawing.Graphics 有大量方法可以让您绘制各种线条、轮廓形状和实体形状
Method |
Typical parameters |
What it draws |
|
画线 |
DrawLine |
Pen, start and end points |
A single straight line 一条直线 |
绘制矩形 |
DrawRectangle |
Pen, position and size |
Outline of a rectangle 矩形的轮廓 |
画椭圆 |
DrawEllipse |
Pen, position and size |
Outline of an ellipse 椭圆的轮廓 |
填充矩形 |
FillRectangle |
Brush, position and size |
Solid rectangle 实心矩形 |
填充椭圆 |
FillEllipse |
Brush, position and size |
Solid ellipse 实心椭圆 |
画线 |
DrawLines |
Pen, array of Points |
一系列线,将数组中的每个点连接到下一个点 |
绘制贝塞尔曲线 |
DrawBezier |
Pen, 4 points |
通过两个端点的平滑曲线,其余两个点用于控制曲线的形状 |
绘制曲线 |
DrawCurve |
Pen, array of points |
通过点的平滑曲线 |
绘制弧线 |
DrawArc |
Pen, rectangle, two angles |
由角度定义的矩形内的圆的一部分 |
绘制闭合曲线 |
DrawClosedCurve |
Pen, array of points |
与 DrawCurve 类似,但也绘制一条直线来闭合曲线 |
画饼图 |
DrawPie |
Pen, rectangle, two angles |
矩形内的楔形轮廓 |
填充馅饼 |
FillPie |
Brush, rectangle, two angles |
矩形内的实心楔形区域 |
绘制多边形 |
DrawPolygon |
Pen, array of points |
与 DrawLines 类似,但也连接第一个点和最后一个点以闭合所绘制的图形。 |
显示图像
public partial class DisplayImageForm : Form { public DisplayImageForm() { InitializeComponent(); this.components = new System.ComponentModel.Container(); this.Size = new System.Drawing.Size(600, 800); this.Text = "Display COMFest Image"; this.BackColor = Color.White; piccy = Image.FromFile(@"E:\图片\微商城\成图\0066dN2mgy6YvHh5ZGo80.jpg"); this.AutoScrollMinSize = piccy.Size; } Image piccy; protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; //选择 this.AutoScrollPosition 作为设备坐标可确保窗口正确滚动,在发生任何滚动之前图像位于客户区域的左上角。 g.DrawImageUnscaled(piccy, this.AutoScrollPosition); base.OnPaint(e); } }
绘制文字
protected override void OnPaint(PaintEventArgs e) { Graphics dc = e.Graphics; Brush blackBrush = Brushes.Black; Brush blueBrush = Brushes.Blue; Font haettenschweilerFont = new Font("Haettenschweiler", 12); Font boldTimesFont = new Font("Times New Roman", 10, FontStyle.Bold); Font italicCourierFont = new Font("Courier", 11, FontStyle.Italic | FontStyle.Underline); dc.DrawString("This is a groovy string", haettenschweilerFont, blackBrush, 10, 10); dc.DrawString("This is a groovy string " + "with some very long text that will never fit in the box", boldTimesFont, blueBrush, new Rectangle(new Point(10, 40), new Size(100, 40))); dc.DrawString("This is a groovy string", italicCourierFont, blackBrush, new Point(10, 100)); base.OnPaint(e); }