c#学习笔记-------------------GDI+绘图编程入门

发布时间 2023-08-10 13:03:46作者: 三流程序媛

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的进一步扩展,它使我们编程更加方便。

 

命名空间和相关类

命名空间:

  1. System.Drawing:这个主要的GDI+命名空间定义了许多类型,实现基本的绘图类型(字体,钢笔,基本画笔等)和无所不能的Graphics对象。

  2. System.Drawing2D:这个命名空间提供高级的二维和失量图像功能。
  3.  

    System.Drawing.Imaging:这个命名空间定义了一些类型实现图形图像的操作。

  4. System.Drawing.Text:这个命名空间提供了操作字体集合的功能。

  5.  System.Drawing.Printing:这个命名空间定义了一些类型实现在打印纸上绘制图像,和打印机交互以及格式化某个打印任务的总体外观等功能。

相关类:

  1. Graphics类:Graphics类封装一个GDI+绘图图面,提供将对象绘制到显示设备的方法,Graphics与特定的设备上下文关联。画图方法都被包括在Graphics类中,在画任何对象(例如:Circle,Rectangle)时,我们首先要创建一个Graphics类实例,这个实例相当于建立了一块画布,有了画布才可以用各种画图方法进行绘图。
  2. Pen类:画笔,定义用于绘制直线和曲线的对象。

  3. Brush类:画刷:定义用于填充图形形状(如矩形、椭圆、饼形、多边形和封闭路径)的内部的对象。只是一个抽象基类。
  4. Font类:字体Font类有两个构造函数:

    第一个是new Font(字体名称,字号),例如,label1.Font=new Font("黑体",9)。

    第二个是new Font(字体名称,字号,字体风格),其中第三个参数是枚举类型。

  5. 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);
        }
    }
}