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

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

 private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Ex()
.DrawLine(, , , )
.DrawLine(, , , ,Pens.Red)
.DrawLine(, , , )
.DrawLine(, , , , new Pen(Color.Blue,3f))
.DrawLine(, , , )
.DrawRectangle(, , , )
.FillRectangle(, , , , Brushes.Red)
.DrawEllipse(, , , , new Pen(Color.Yellow, 3f))
.FillEllipse(, , , ,Brushes.Green)
.DrawString("haha",new PointF(200f,200f))
.DrawString("leilei", new PointF(100f, 200f),new Font("微软雅黑",30f));
}

画出来的效果如下:

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

 public static class GDIEx
{
public static GraphicsEx Ex(this Graphics g)
{
return new GraphicsEx(g);
}
}
public class GraphicsEx : IDisposable
{
readonly Graphics g;
Pen pen = Pens.Black;
Brush brush = Brushes.Black;
Font font = new Font(FontFamily.GenericSerif,);
internal GraphicsEx(Graphics g)
{
this.g = g;
}
public void Dispose()
{
g.Dispose();
pen = null;
brush = null;
font = null;
}
public GraphicsEx DrawLine(int x1, int y1, int x2, int y2,[Optional]Pen pen)
{
if (pen != null)
this.pen = pen;
g.DrawLine(this.pen, x1, y1, x2, y2);
return this;
}
public GraphicsEx DrawLine(Point p1, Point p2,[Optional]Pen pen)
{
if (pen != null)
this.pen = pen;
g.DrawLine(this.pen, p1, p2);
return this;
}
public GraphicsEx DrawRectangle(Rectangle rect,[Optional]Pen pen)
{
if (pen != null)
this.pen = pen;
g.DrawRectangle(this.pen, rect);
return this;
}
public GraphicsEx DrawRectangle(int left,int top,int width,int height,[Optional]Pen pen)
{
if(pen != null)
this.pen = pen;
g.DrawRectangle(this.pen, left, top, width, height);
return this;
}
public GraphicsEx FillRectangle(Rectangle rect, [Optional]Brush brush)
{
if(brush != null)
this.brush = brush;
g.FillRectangle(this.brush, rect);
return this;
}
public GraphicsEx FillRectangle(int left, int top, int width, int height, [Optional]Brush brush)
{
if (brush != null)
this.brush = brush;
g.FillRectangle(this.brush, left, top, width, height);
return this;
}
public GraphicsEx DrawEllipse(Rectangle rect, [Optional]Pen pen)
{
if (pen != null)
this.pen = pen;
g.DrawEllipse(this.pen, rect);
return this;
}
public GraphicsEx DrawEllipse(int left, int top, int width, int height, [Optional]Pen pen)
{
if (pen != null)
this.pen = pen;
g.DrawEllipse(this.pen, left, top, width, height);
return this;
}
public GraphicsEx FillEllipse(Rectangle rect, [Optional]Brush brush)
{
if (brush != null)
this.brush = brush;
g.FillEllipse(this.brush, rect);
return this;
}
public GraphicsEx FillEllipse(int left, int top, int width, int height, [Optional]Brush brush)
{
if (brush != null)
this.brush = brush;
g.FillEllipse(this.brush, left, top, width, height);
return this;
}
public GraphicsEx DrawString(string str, RectangleF rect,[Optional]Font font, [Optional]Brush brush)
{
if (font != null)
this.font = font;
if (brush != null)
this.brush = brush;
g.DrawString(str, this.font, this.brush, rect);
return this;
}
public GraphicsEx DrawString(string str, PointF p, [Optional]Font font, [Optional]Brush brush)
{
if (font != null)
this.font = font;
if (brush != null)
this.brush = brush;
g.DrawString(str, this.font, this.brush, p);
return this;
}
}

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

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

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

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

像Linq一样来使用Graphics的更多相关文章

  1. [C#] Timer + Graphics To Get Simple Animation (简单的源码例子,适合初学者)

    >_<" 这是一个非常简单的利用C#的窗口工程创立的程序,用来做一个简单的动画,涉及Timer和Graphics,适合初学者,高手略过~

  2. WinForms 使用Graphics绘制字体阴影

    C#以两种方法实现文字阴影效果,同时还实现了简单的动画效果: 一种是对文本使用去锯齿的边缘处理,在两个不同的位置绘制文本,形成阴影: 另一个是以阴影为线条,构造影线画刷,先画背景再画前景,使用grap ...

  3. GDI+画图类Graphics的使用

    一:基础定义 #region 定义线尾.线头为箭头.字体和笔刷 Pen p = );//定义画笔 蓝色,宽度为1(坐标显示颜色) p.EndCap = LineCap.ArrowAnchor;//定义 ...

  4. MVC+Spring.NET+NHibernate .NET SSH框架整合 C# 委托异步 和 async /await 两种实现的异步 如何消除点击按钮时周围出现的白线? Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法

    MVC+Spring.NET+NHibernate .NET SSH框架整合   在JAVA中,SSH框架可谓是无人不晓,就和.NET中的MVC框架一样普及.作为一个初学者,可以感受到.NET出了MV ...

  5. 【转】WinForms 使用Graphics绘制字体阴影

    转自:http://www.cnblogs.com/LonelyShadow/p/3893743.html C#以两种方法实现文字阴影效果,同时还实现了简单的动画效果: 一种是对文本使用去锯齿的边缘处 ...

  6. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

  7. 模仿ArcGIS用Graphics重绘的直方图分级调节器

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  8. .net 反射访问私有变量和私有方法 如何创建C# Closure ? C# 批量生成随机密码,必须包含数字和字母,并用加密算法加密 C#中的foreach和yield 数组为什么可以使用linq查询 C#中的 具名参数 和 可选参数 显示实现接口 异步CTP(Async CTP)为什么那样工作? C#多线程基础,适合新手了解 C#加快Bitmap的访问速度 C#实现对图片文件的压

    以下为本次实践代码: using System; using System.Collections.Generic; using System.ComponentModel; using System ...

  9. Winform中使用zxing和Graphics实现自定义绘制二维码布局

    场景 zxing.dll下载 https://download.csdn.net/download/badao_liumang_qizhi/11623214 效果 实现 根据上面文章中将简单的二维码生 ...

随机推荐

  1. poj 2449 第k短路径

    思路: 利用一个估计函数g[i]=dis[i]+len.其中len为队列出来的点当前已经走了的距离.dis[i]为该点到终点的最短路径.这样我们只要将点按g[i]的升序在队列你排序,每次取出最小的g[ ...

  2. WDatePicker 屏蔽onchange事件的解决办法

    受下面文章的启发,使用DatePicker自带的年月日相关的change事件,可以“勉强”实现input控件的onchange(),直接上代码: 1.第一种方式:利用DatePicker提供的年.月. ...

  3. IOS Delegate & protocal

    总结一下: delegate是一个方式,程序组成单元之间分工的一种协调思想 protocal 这个东西不能单独说,要与它相关的两个主要东西一起说,一个是 委托者 通常是VIEW, 一个是被委托者 通常 ...

  4. Genymotion安卓模拟器,性能最好

    老笔记本用AndroidSDK自带的模拟器 启动慢 运行卡 用了Genymotion启动快,运行响应媲美真机 想起学生时代,那时候智能手机还未完全普及 也用模拟器玩过”电脑里的手机“.

  5. [盈利指导] [原创]五蕴皆空:App推广干货,排名数据分析优化效果

          App盈利交流论坛版主第一帖2015年3月份,在百度上了一款赛车类游戏(不说什么名字了怕被打包),后台起名叫002,刚开始上的时候一天只有几元钱,但是游戏还是倾注了不少心血的,觉得不甘心, ...

  6. JSP之Cookie

    Cookie是小段的文本信息,在网络服务器上生成,并发送给浏览器,通过使用cookie可以标识用户身份,记录用户名和密码,跟踪重复等. 首先创建index.jsp: <%@page import ...

  7. 第五十二篇、 OC获取视频的第一帧图片thumbnailImage

    获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...

  8. 在windows7中使用计划任务命令SCHTASKS查询计划任务失败的解决方案

    造成这种原因是因为编码问题: 因此需要修改编码:chcp schtasks.exe /query 会报错     错误: 无法加载列资源. 修改编码为936为436就可以允许啦,但是中文不不能显示啦. ...

  9. Linux小白最佳实践:《超容易的Linux系统管理入门书》(连载五)Linux系统的对话方式

    本篇是Linux小白最佳实践第5篇,目的就是让白菜们了解Linux进程之间是如何对话的.之前连载的几篇,在微信上引起了很多的反响,有人也反映图多文字少,感觉没有干货.本篇选了大部分是实战讲解的&quo ...

  10. linux同步

    1. 内核同步 主要是防止多核处理器同时访问修改某段代码,或者在对设备驱动程序进行临界区的保护. 1 .互斥量 头文件 #include<linux/mutex.h> 初始化方法: 静态初 ...