GDI+概述
参考文章:https://www.cnblogs.com/funiyi816/p/17122625.html
https://www.cnblogs.com/xiaowie/p/8819684.html
编写图形程序时需要使用GDI(Graphics Device Interface,图形设备接口),
从程序设计的角度看,GDI包括两部分:
一部分是GDI对象,
另一部分是GDI函数。
GDI对象定义了GDI函数使用的工具和环境变量,而GDI函数使用GDI对象绘制各种图形,
在C#中,进行图形程序编写时用到的是GDI+(Graphice Device Interface Plus图形设备接口)版本,
GDI+是GDI的进一步扩展,它使我们编程更加方便。
命名空间和相关类
命名空间:
-
System.Drawing:这个主要的GDI+命名空间定义了许多类型,实现基本的绘图类型(字体,钢笔,基本画笔等)和无所不能的Graphics对象。
- System.Drawing2D:这个命名空间提供高级的二维和失量图像功能。
-
System.Drawing.Imaging:这个命名空间定义了一些类型实现图形图像的操作。
-
System.Drawing.Text:这个命名空间提供了操作字体集合的功能。
-
System.Drawing.Printing:这个命名空间定义了一些类型实现在打印纸上绘制图像,和打印机交互以及格式化某个打印任务的总体外观等功能。
相关类:
- Graphics类:Graphics类封装一个GDI+绘图图面,提供将对象绘制到显示设备的方法,Graphics与特定的设备上下文关联。画图方法都被包括在Graphics类中,在画任何对象(例如:Circle,Rectangle)时,我们首先要创建一个Graphics类实例,这个实例相当于建立了一块画布,有了画布才可以用各种画图方法进行绘图。
-
Pen类:画笔,定义用于绘制直线和曲线的对象。
- Brush类:画刷:定义用于填充图形形状(如矩形、椭圆、饼形、多边形和封闭路径)的内部的对象。只是一个抽象基类。
- Font类:字体Font类有两个构造函数:
第一个是new Font(字体名称,字号),例如,label1.Font=new Font("黑体",9)。
第二个是new Font(字体名称,字号,字体风格),其中第三个参数是枚举类型。
- Image类:Image类和Printing类都是常用的操作图像和打印的类,它们提供了丰富的方法和属性,可以方便地实现各种图像的处理和打印。
Graphics类常用方法:
- 画线条
DrawLine 绘制一条连接由坐标对象指定的两个点的线条
DrawLines 绘制一列连接一组Point结构的线段
DrawBezier 绘制由四个Point结构定义的贝塞尔样条
DrawBeziers 从Point结构的数组绘制一系列贝塞尔样条
DrawCurve 绘制经过一组指定的Point结构的基数样条 - 画可填充线条
DrawEllipse 绘制一个由一对坐标、宽度和高度指定的椭圆
DrawPath 绘制GraphicsPath对象
DrawPie 绘制一个扇形,该扇形由一个坐标对象,宽度和高度,以及两条射线所指定的椭圆指定
DrawPolygon 绘制由一组Point结构定义的多边形
DrawRectangle 绘制由坐标对。宽度和高度指定的矩形
DrawRectangles 绘制一系列由Rectangle结构指定的矩形
DrawArc 绘制一段弧线,它表示由一对坐标、宽高指定的椭圆部分 - 填充区域
FillEllipse 填充边框所定义的椭圆内部,该边框由一对坐标、一个高度和一个宽度指定
FillPath 填充GraphicsPath对象的内部
FillPie 填充扇形内部
FillPolygon 填充多边形内部
FillRectangle 填充由一对坐标、一个宽度和一个高度指定的矩形内部
FillRectangles 填充由Rectangle结构指定的一些列矩阵的内部
FillRegion 填充Region对象的内部 - 画字符串、图画、图标
DrawString 在指定位置并且用指定的Brush和Font对象绘制指定的文本字符串
DrawIcon 在指定坐标处绘制由指定的Icon对象表示的图像
DrawImage 在指定的位置并且按原始大小绘制指定的Image对象 - 其他
MeasureString(String, Font) 测量用指定的 Font 绘制的指定字符串。
FromImage 从指定的Image对象创建行的Graphics对象
Save 保存此Graphics对象的当前状态,并且GraphicsState对象标识保存的状态
Clear 清除整个绘图面并以指定背景色填充
Dispose 释放由此Graphics对象使用的所有资源
绘制图形(线型,字符串,图片)
开始实操之前我们要先了解winform的坐标结构:
坐标系统:
GDI+定义了三种坐标系统,并提供了三种坐标转换的方法Graphics.TransformPoints()。
- 全局坐标系统。
- 页面(Page)坐标系统:左上角为原点,横向x轴向右为正方向,纵向y轴向下为正方向。单位为像素。这是默认的坐标系统。
- 设备坐标系统:可以指定特定测量单位的页面(Page)坐标系统。如果单位为像素,和页面(Page)坐标系统相同。
点结构有两个成员:X,Y,表示点的x轴和y轴的坐标。其常用构造函数如下:
Point p1=new Point(int X,int Y);//X,Y为整数 PointF p2=new PointF(float X,floa Y);//X,Y为浮点数
Size和SizeF用来表示尺寸大小,有两个成员:Width和Height。常用构造函数如下:
public Size(int width,int height); public SizeF(float width,float height);
结构Rectangle和RectangleF用来表示一个矩形,常用构造函数如下:
//参数为矩形左上角坐标的点结构location和代表矩形宽和高的Size结构size Rectangle(Point location,Size size);//参数也可为PointF和SizeF //参数为矩形左上角x和y坐标,宽,高 Rectangle(int X,int Y,int width,int height);//X和Y也可为float
画直线
//画实线 Pen pen = new Pen(Color.Red, 3); //确定线的首位位置 Point point1 = new Point(10, 50); Point point2 = new Point(250, 50); Graphics g = this.CreateGraphics(); g.DrawLine(pen, point1, point2);
画刷
Rectangle rect1 = new Rectangle(20, 80, 250, 100); // (实心实心刷) SolidBrush sbrush = new SolidBrush(Color.DarkOrchid); //(纹理刷) TextureBrush textureBrush = new TextureBrush(new Bitmap(@"e:/123.jpg")); //(梯度、线性渐进刷) LinearGradientBrush lbrush = new LinearGradientBrush(rect1, Color.DarkOrange, Color.Aquamarine, 45); //(阴影刷) HatchBrush hbrush = new HatchBrush(HatchStyle.DiagonalCross, Color.DarkOrange, Color.Aquamarine); e.Graphics.FillRectangle(sbrush, rect1); // (实心刷) e.Graphics.FillRectangle(textureBrush, rect1); //(纹理刷) e.Graphics.FillRectangle(lbrush, rect1); //(梯度刷) e.Graphics.FillRectangle(hbrush, rect1); //(阴影刷)
写字
//当整个窗体被重新绘制时调用的方法 Graphics g = this.CreateGraphics(); Pen p = new Pen(Color.Green); g.DrawLine(p,new Point(50,50),new Point(200,100)); ///第一个是new Font(字体名称,字号),例如,label1.Font=new Font("黑体",9)。 //第二个是new Font(字体名称, 字号,字体风格),其中第三个参数是枚举类型。 g.DrawString("好好学习", new Font("隶书", 20), new SolidBrush(Color.Blue), new Point(200, 100)); g.DrawString("好好学习", new Font("隶书", 20,FontStyle.Strikeout), new SolidBrush(Color.Blue), new Point(200, 100));
画图
private void Form1_Paint(object sender, PaintEventArgs e) { //当整个窗体被重新绘制时调用的方法 Graphics g = this.CreateGraphics(); g.DrawImage(Properties.Resources.Boss, new Point(210, 110)); Pen p = new Pen(Color.Green); g.DrawLine(p,new Point(50,50),new Point(200,100)); }
实例:坦克大战
利用用GDI+制作一款小游戏,效果图如下:
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using TankWarHH.Properties; using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar; namespace TankWarHH { public partial class Form1 : Form { private Thread t; private static Graphics windowG; private static Bitmap backBmp; public Form1() { InitializeComponent(); this.StartPosition = FormStartPosition.CenterScreen; this.FormBorderStyle = FormBorderStyle.FixedDialog; windowG=this.CreateGraphics(); backBmp = new Bitmap(900, 900); GameFrameWork.g = Graphics.FromImage(backBmp); t = new Thread(new ThreadStart(GameMainThread)); t.Start(); } private static void GameMainThread() { //GameFrameWork GameFrameWork.Start(); int sleepTime = 1000 / 60; while (true) { GameFrameWork.g.Clear(Color.Black); GameFrameWork.Update(); windowG.DrawImage(backBmp, 0, 0); Thread.Sleep(sleepTime); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { t.Abort(); } private void Form1_KeyDown(object sender, KeyEventArgs e) { GameObjectManage.KeyDown(e); } private void Form1_KeyUp(object sender, KeyEventArgs e) { GameObjectManage.KeyUp(e); } } public class GameFrameWork { public static Graphics g; public static void Start() { GameObjectManage.GreateMap(); GameObjectManage.CreateMyTank(); } public static void Update() { GameObjectManage.DrawMap(); GameObjectManage.DrawMyTank(); } public static void End() { } } public abstract class GameObject { public int X { get; set; } public int Y { get; set; } public abstract Image GetImage(); public void DrawSelf() { Graphics g=GameFrameWork.g; g.DrawImage(GetImage(), new Point(X, Y)); } public virtual void Update() { DrawSelf(); } } public class NotMovething : GameObject { public Image image { get; set; } public override Image GetImage() { return image; } public NotMovething(int x, int y,Image img) { this.X = x; this.Y = y; this.image = img; } } public enum Direction { Up, Down, Left, Right } public class Movething : GameObject { public Bitmap Up { get; set; } public Bitmap Down { get; set; } public Bitmap Left { get; set; } public Bitmap Right { get; set; } public int Speen { get; set; } public Direction Dir { get; set; } public override Image GetImage() { Bitmap bitmap = null; switch (Dir) { case Direction.Up: bitmap = Up; break; case Direction.Down: bitmap = Down; break; case Direction.Left: bitmap = Left; break; case Direction.Right: bitmap = Right; break; default: return Up; } bitmap.MakeTransparent(Color.Black); return bitmap; } } public class MyTake : Movething { public bool IsMoving { get; set; } public MyTake(int x,int y,int speed,Direction dir) { this.X= x; this.Y= y; this.Speen = speed; this.Dir = dir; Up = Resources.MyTankUp; Down=Resources.MyTankDown; Left = Resources.MyTankLeft; Right = Resources.MyTankRight; } internal void KeyDown(KeyEventArgs args) { switch (args.KeyCode) { case Keys.W: Dir = Direction.Up; IsMoving = true; break; case Keys.S: Dir = Direction.Down; IsMoving = true; break; case Keys.A: Dir = Direction.Left; IsMoving = true; break; case Keys.D: Dir = Direction.Right; IsMoving = true; break; case Keys.Space: Attack(); break; } } private void Attack() { throw new NotImplementedException(); } private void Move() { if (!IsMoving) { return; } switch(Dir) { case Direction.Up: Y -= this.Speen; break; case Direction.Down: Y += Speen; break; case Direction.Left: X -= Speen; break; case Direction.Right: X += Speen; break; } } internal void KeyUp(KeyEventArgs args) { switch (args.KeyCode) { case Keys.W: IsMoving = false; break; case Keys.S: IsMoving = false; break; case Keys.A: IsMoving = false; break; case Keys.D: IsMoving = false; break; } } } public class EnemyTank : Movething { } public class Bullet : Movething { } public class GameObjectManage { private static List<NotMovething> walllist=new List<NotMovething> (); private static List<NotMovething> steellist=new List<NotMovething> (); private static NotMovething boss; private static MyTake mytake; public static void DrawMap() { foreach(var wall in walllist) { wall.DrawSelf(); } foreach(var steel in steellist) { steel.DrawSelf(); } boss.DrawSelf(); } public static void DrawMyTank() { mytake.DrawSelf(); } public static void GreateMap() { for(int i = 1; i < (815 / 30); i += 2) { walllist.AddRange(GreateWall(i, 1, 5, Resources.wall)); } for(int i=2; i < (785 / 30); i += 2) { walllist.AddRange(GreateWall(i, 7, 3, Resources.wall)); } for (int i = 2; i < (785 / 30); i += 4) { steellist.AddRange(GreateWall(i, 2, 3, Resources.steel)); } for (int i = 1; i < 24; i += 5) { walllist.AddRange(GreateWall(i, 11, 2, Resources.wall)); walllist.AddRange(GreateWall(i+1, 11, 2, Resources.wall)); walllist.AddRange(GreateWall(i+2, 11, 2, Resources.wall)); } steellist.AddRange(GreateWall(2, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(3, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(4, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(5, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(7, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(8, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(9, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(10, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(12, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(13, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(14, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(15, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(17, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(18, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(19, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(20, 14, 1, Resources.wall)); steellist.AddRange(GreateWall(22, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(23, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(24, 14, 1, Resources.steel)); steellist.AddRange(GreateWall(25, 14, 1, Resources.steel)); for (int i = 1; i < (815 / 30); i += 2) { walllist.AddRange(GreateWall(i, 16, 5, Resources.wall)); } for (int i = 2; i < (785 / 30); i += 2) { if (i != 12 && i != 14 && i != 10 && i != 16) { walllist.AddRange(GreateWall(i, 22, 4, Resources.wall)); } if (i == 10 || i == 16) { walllist.AddRange(GreateWall(i, 22, 2, Resources.wall)); } } walllist.AddRange(CreateBosswall(12, 24, 2, Resources.wall)); walllist.AddRange(CreateBosswall2(14, 24, 2, Resources.wall)); walllist.AddRange(GreateWall(12, 23, 1, Resources.wall)); walllist.AddRange(GreateWall(13, 23, 1, Resources.wall)); walllist.AddRange(GreateWall(14, 23, 1, Resources.wall)); CreateBoss(13, 25, Resources.Boss); } public static void CreateMyTank() { int x = 11 * 30; int y = 25 * 30; mytake = new MyTake(x, y, 2, Direction.Up); } private static List<NotMovething> GreateWall(int x,int y,int count,Image image) { List<NotMovething> walllist = new List<NotMovething>(); int xposition = x * 30; int yposition = y * 30; for (int i = yposition; i < yposition + count * 30; i += 15) { NotMovething wall = new NotMovething(xposition, i, image); NotMovething wall2 = new NotMovething(xposition + 15, i, image); walllist.Add(wall); walllist.Add(wall2); } return walllist; } private static List<NotMovething> CreateBosswall(int x, int y, int count, Image image) { List<NotMovething> bosslist = new List<NotMovething>(); int xposition = x * 30; int yposition = y * 30; for (int i = yposition; i < yposition + count * 30; i += 15) { NotMovething wall = new NotMovething(xposition, i, image); walllist.Add(wall); } return walllist; } private static List<NotMovething> CreateBosswall2(int x, int y, int count, Image image) { List<NotMovething> bosslist = new List<NotMovething>(); int xposition = x * 30; int yposition = y * 30; for (int i = yposition; i < yposition + count * 30; i += 15) { NotMovething wall2 = new NotMovething(xposition + 15, i, image); walllist.Add(wall2); } return walllist; } private static void CreateBoss(int x, int y, Image img) { int xPosition = x * 30; int yPosition = y * 30; boss = new NotMovething(xPosition, yPosition, img); } internal static void KeyDown(KeyEventArgs args) { mytake.KeyDown(args); } internal static void KeyUp(KeyEventArgs args) { mytake.KeyUp(args); } } }