C#实现简易绘图工具
一. 引言
实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.
Tutorial任务
设计一个具有基本功能的画图软件**
·包括简单的新建文件,保存,重新绘图等功能**
·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**
·设计一个合理舒适的UI界面**
注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识
二.实验环境
Windows系统下的visual studio 2017
C#窗体应用程序
三.实验流程
1.首先,新建一个项目,取名为"我的画板"
对于画板来说,其中很重要的就是工具,因此,我们需要创建一个类用来存放需要的画图工具,比较常见的功能有绘制直线,矩形,椭圆形,圆形,正方形,以及绘制填充矩形,椭圆形,圆形等,同样,我们还需要橡皮对画错的地方进行修改.
在项目中创建一个名为drawtools的类,如下图所示:

2.在创建好的类中创建我们的工具
(1)声明一些变量
public Graphics DrawTools_Graphics; //目标绘图板
private Pen p;
private int lineWidth = 3;//划线的宽度设置为3
private Image orginalImg;//原始画布,用来保存已经完成的绘图过程
private Color drawColor = Color.Black;//绘图的画笔颜色初始化为黑色
private Color backColor = Color.White;//绘图区域的背景颜色
private Graphics newgraphics;//中间画板
private Image finishImg;//中间画布,用来保存绘图过程中的痕迹
为了更加有效地防止造成图片抖动,从而防止记录不必要的绘图过程中的痕迹,我们的画要先在中间画板上完成,然后再将绘制好的图画一次性导到目标画板上
(2)属性部分,通过get和set方法设置绘图颜色,背景颜色,线条粗细以及获得原始画布
//绘图颜色属性
public Color Drawcolor
{
get { return drawColor; }
set
{
drawColor = value;
p.Color = value;//将画笔颜色也调整为所需要的颜色
}
}
//背景颜色属性
public Color Backcolor
{
get { return backColor; }
set
{
backColor = value;
}
}
//线条粗细属性
public int LineWidth
{
get { return lineWidth; }
set
{
lineWidth = value;
p.Width = value;//将画笔的粗细也设置为线条宽度
}
}
//创建画布
public Image OrginalImg
{
get { return orginalImg; }
set
{
finishImg = (Image)value.Clone();
orginalImg = (Image)value.Clone();//创建两个副本,作为原始画布和中间画布
}
}
(3)使用构造函数对绘图工具进行初始化
//bool变量startDraw表示是否要开始绘图
public bool startDraw = false;
//设置绘图起点
public PointF startPoint;
/// <summary>
/// 初始化绘图工具
/// </summary>
/// <param name="g">绘图板</param>
/// <param name="c">绘图颜色</param>
/// <param name="img">初始画布</param>
/// <param name="linewidth">线条宽度</param>
public DrawTools(Graphics g,Color c,Image img,int linewidth)
{
this.DrawTools_Graphics = g;
this.drawColor = c;
this.p = new Pen(c, linewidth);
this.finishImg = (Image)img.Clone();
this.OrginalImg = (Image)img.Clone();
}
(4)绘制直线,矩形,圆形,正方形,填充圆形,填充矩形,填充正方形,填充椭圆形,这一部分包含以下几个步骤:
(i)实例化中间画板,此时的画布为上次绘制结束时的副本(当第一次绘制时,画布是初始化的画布副本)
(ii)按照选择的绘图样式在中间画板上进行绘制
(iii)绘制结束的图画应该画到中间画布上
这里面有一个值得注意的问题,那就是在绘图过程中,用户需要能够实时地看到自己画画的过程(体现在目标画板上),所以在鼠标移动过程中,为了看到效果,绘制的图画依然要显示在目标画板上,而最终绘制结束时的图片应当在鼠标松开时完成,此时才将中间图画最后导出到原始画布上
Image img = (Image)OrginalImg.Clone();//为了防止直接对原始画布进行改写
newgraphics = Graphics.FromImage(img);//实例化中间画板
(4a)绘制直线,也就是在绘画起始位置与鼠标移动到的位置之间绘制一条直线
case "Line":
{
newgraphics.DrawLine(p, startPoint, new Point(e.X, e.Y));
break;
}
(4b)绘制一个矩形
值得注意的是,鼠标移动到的位置与起始位置之间横向距离的绝对值就是矩形的宽,纵向距离的绝对值就是矩形的高,但是由于鼠标移动的位置可能会出现在起始位置的左侧或者上侧的情况,因此要分类进行讨论:
例如,在鼠标移动位置位于起始位置的左侧时,由于矩形的长已经确定,所以不妨将起始位置改为鼠标最后移动到的位置,以免出现当鼠标移动到起始位置左侧时,无法成功绘制矩形.也就是说,我们要让矩形绘制的位置位于起始位置的右下方,讨论方式见以下:
case "Rectangle":
{
float width = Math.Abs(e.X - startPoint.X);//确定矩形的宽
float height = Math.Abs(e.Y - startPoint.Y);//确定矩形的高
PointF rectStartPoint = startPoint;//设置最终画出矩形的起始位置
if (e.X < rectStartPoint.X)
{
rectStartPoint.X = e.X;//如果鼠标所处位置在画图起始位置左边,就把最终起始位置赋值为鼠标位置
}
if (e.Y < rectStartPoint.Y)
{
rectStartPoint.Y = e.Y;
}
newgraphics.DrawRectangle(p, rectStartPoint.X, rectStartPoint.Y, width, height);
break;
}
(4c)绘制一个正方形
与绘制矩形基本类似,区别在于,正方形的长和宽是等长的,因此,要选择矩形的长和宽中较短的边(或者较长的边)作为正方形的边长,代码如下:
case "Square":
{
float width = Math.Abs(e.X - startPoint.X);
float height = Math.Abs(e.Y - startPoint.Y);
float bian = (width < height) ? width : height;
PointF squareStartPoint = startPoint;
if (e.X < startPoint.X)
{
squareStartPoint.X = startPoint.X - bian;//注意,这样设置是为了防止出现正方形到处移动的情况
}
if (e.Y < startPoint.Y)
{
squareStartPoint.Y = startPoint.Y - bian;
}
newgraphics.DrawRectangle(p, squareStartPoint.X, squareStartPoint.Y, bian, bian);
break;
}
写到这里我们会发现,用户在绘制图形时,如果向左上角进行绘制,表面上看是矩形的左上角向左上方移动,实际上则是从鼠标最后拖拽到的位置开始进行向右下角的绘制(也就是绘制起点是在矩形左上角,进行右下角方向的绘制)
(4d)绘制一个椭圆形
直接使用DrawEllipse的方法对于椭圆形进行绘制,这是一个用矩形边框画出椭圆的方法,可以理解为长是鼠标移动位置到起始位置x轴方向上的距离.同样,宽是鼠标移动位置到起始位置y轴方向上的距离.完全类比绘制矩形的情况,用代码实现绘制椭圆形
case "Ellipse":
{
float width = Math.Abs(e.X - startPoint.X);
float height = Math.Abs(e.Y - startPoint.Y);
PointF rectStartPoint = startPoint;
float bian = (width < height) ? width : heig


5309

被折叠的 条评论
为什么被折叠?



