zoukankan      html  css  js  c++  java
  • 像Linq一样来使用Graphics

    像Linq一样来使用Graphics

    Linq的链式编程用起来总是那样畅快淋漓,可惜在C#中并不是每时每刻都能有这么畅快的感觉,其中使用Graphics的时候就是,每次用Graphics绘制大量图形时尤其如此。GDI+的API功能很强大,但是在实际编码中,很多重复性的工作总是让我感觉到用起来很繁琐,于是我就设计了这样一个类库,将C#中的Graphics类进行了二次封装,让其可以和Linq一样,用起来“如沐春风”。

    先来看一段简单的示例代码吧。下面代码就是在一个窗体上绘制一系列图形,可以看出和原来的Graphics相比,编码量更小,代码也更优雅。

    复制代码
     1 private void Form1_Paint(object sender, PaintEventArgs e)
     2         {
     3             e.Graphics.Ex()
     4                 .DrawLine(10, 10, 50, 50)
     5                 .DrawLine(50, 50, 100, 50,Pens.Red)
     6                 .DrawLine(100, 50, 100, 100)
     7                 .DrawLine(100, 100, 150, 100, new Pen(Color.Blue,3f))
     8                 .DrawLine(150, 100, 150, 150)
     9                 .DrawRectangle(150, 50, 100, 100)
    10                 .FillRectangle(150, 50, 100, 100, Brushes.Red)
    11                 .DrawEllipse(150, 50, 50, 100, new Pen(Color.Yellow, 3f))
    12                 .FillEllipse(150, 50, 50, 100,Brushes.Green)
    13                 .DrawString("haha",new PointF(200f,200f))
    14                 .DrawString("leilei", new PointF(100f, 200f),new Font("微软雅黑",30f));
    15         }
    复制代码

    画出来的效果如下:

    下面就是我对Graphics二次封装的具体代码,目前还只能绘制Line、Rectangle、Ellipse和string

    复制代码
      1 public static class GDIEx
      2     {
      3         public static GraphicsEx Ex(this Graphics g)
      4         {
      5             return new GraphicsEx(g);
      6         }
      7     }
      8     public class GraphicsEx : IDisposable
      9     {
     10         readonly Graphics g;
     11         Pen pen = Pens.Black;
     12         Brush brush = Brushes.Black;
     13         Font font = new Font(FontFamily.GenericSerif,10);
     14         internal GraphicsEx(Graphics g)
     15         {
     16             this.g = g;
     17         }
     18         public void Dispose()
     19         {
     20             g.Dispose();
     21             pen = null;
     22             brush = null;
     23             font = null;
     24         }
     25         public GraphicsEx DrawLine(int x1, int y1, int x2, int y2,[Optional]Pen pen)
     26         {
     27             if (pen != null)
     28                 this.pen = pen;
     29             g.DrawLine(this.pen, x1, y1, x2, y2);
     30             return this;
     31         }
     32         public GraphicsEx DrawLine(Point p1, Point p2,[Optional]Pen pen)
     33         {
     34             if (pen != null)
     35                 this.pen = pen;
     36             g.DrawLine(this.pen, p1, p2);
     37             return this;
     38         }
     39         public GraphicsEx DrawRectangle(Rectangle rect,[Optional]Pen pen)
     40         {
     41             if (pen != null)
     42                 this.pen = pen;
     43             g.DrawRectangle(this.pen, rect);
     44             return this;
     45         }
     46         public GraphicsEx DrawRectangle(int left,int top,int width,int height,[Optional]Pen pen)
     47         {
     48             if(pen != null)
     49                 this.pen = pen;
     50             g.DrawRectangle(this.pen, left, top, width, height);
     51             return this;
     52         }
     53         public GraphicsEx FillRectangle(Rectangle rect, [Optional]Brush brush)
     54         {
     55             if(brush != null)
     56                 this.brush = brush;
     57             g.FillRectangle(this.brush, rect);
     58             return this;
     59         }
     60         public GraphicsEx FillRectangle(int left, int top, int width, int height, [Optional]Brush brush)
     61         {
     62             if (brush != null)
     63                 this.brush = brush;
     64             g.FillRectangle(this.brush, left, top, width, height);
     65             return this;
     66         }
     67         public GraphicsEx DrawEllipse(Rectangle rect, [Optional]Pen pen)
     68         {
     69             if (pen != null)
     70                 this.pen = pen;
     71             g.DrawEllipse(this.pen, rect);
     72             return this;
     73         }
     74         public GraphicsEx DrawEllipse(int left, int top, int width, int height, [Optional]Pen pen)
     75         {
     76             if (pen != null)
     77                 this.pen = pen;
     78             g.DrawEllipse(this.pen, left, top, width, height);
     79             return this;
     80         }
     81         public GraphicsEx FillEllipse(Rectangle rect, [Optional]Brush brush)
     82         {
     83             if (brush != null)
     84                 this.brush = brush;
     85             g.FillEllipse(this.brush, rect);
     86             return this;
     87         }
     88         public GraphicsEx FillEllipse(int left, int top, int width, int height, [Optional]Brush brush)
     89         {
     90             if (brush != null)
     91                 this.brush = brush;
     92             g.FillEllipse(this.brush, left, top, width, height);
     93             return this;
     94         }
     95         public GraphicsEx DrawString(string str, RectangleF rect,[Optional]Font font, [Optional]Brush brush)
     96         {
     97             if (font != null)
     98                 this.font = font;
     99             if (brush != null)
    100                 this.brush = brush;
    101             g.DrawString(str, this.font, this.brush, rect);
    102             return this;
    103         }
    104         public GraphicsEx DrawString(string str, PointF p, [Optional]Font font, [Optional]Brush brush)
    105         {
    106             if (font != null)
    107                 this.font = font;
    108             if (brush != null)
    109                 this.brush = brush;
    110             g.DrawString(str, this.font, this.brush, p);
    111             return this;
    112         }
    113     }
    复制代码

    封装思想其实比较简单,封装的主体就是类GraphicsEx,该类根据构造函数中传入的Graphics进行绘图,并且绘制函数的签名尽量和Graphics的接口保持一致,以增加易用性,并且每个绘制函数都会返回实例本身,以供不断的调用。

    所有的画笔、画刷或者其它与绘制内容无关的绘制参数都采用可选参数,这样做的目的很简单,从文章开始的示例中可以看出,在绘制一些Line的步骤中并没有指明所用的画笔,这时Graphics绘制时会自动采用上一次使用的画笔或者初始画笔进行绘制,这样在使用同一种画笔绘制多条直线,或者绘制多种不同图形时,可以省去每一步都必须要指定画笔的工作,减少编码量。

    我对GraphicsEx的构造函数访问级别进行了控制,设置为internal级别,只让其在程序集内可见,并且通过构建一个Graphics的扩展方法,用来创建GraphicsEx的实例,用来代替其本身构造函数的功能,这样在使用时就显得更加自然一些。

    就写这么多了,不知道大家看完我这样的封装有什么自己的看法,希望不吝赐教,在回帖中和我交流,谢谢!

     
     
     
    标签: c#Graphics
  • 相关阅读:
    直面焦虑烦恼 谈谈成长
    Makefile入门1
    递归
    极客时间的专栏
    作者介绍
    1.试除法判定质数 2.分解质因数 质数
    17.没有上司的舞会 树形DP
    17.二分图的最大匹配
    16.染色法判定二分图
    15.Kruskal算法求最小生成树
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3245764.html
Copyright © 2011-2022 走看看