最近在学C# GDI+ 做了一个绘图小程序,模仿电脑上自带的画图。效果如下:
本程序采用了双缓冲技术,但不会出现屏幕闪烁问题,更不会出现改变窗口大小出现的重绘问题。
下面我来讲讲思路:
public PointF startp;//初始点
//Bitmap bit;
public Font f = new Font("Arial", 16);//字体
public Graphics aim, help;//目标画板和辅助画板
public Image O, F;//画布
public Pen p = new Pen(Color.Black);//初始化笔
public Color color = Color.Black;//颜色
public string s = "请输入你要输入的文字";
public DrawTools(Graphics g,Image img)//构造函数
由两个画板,辅助画板负责将说要绘制的图画画在BitMap 上,保存下来,然后目标画板在将辅助画板画的BitMap ---- DrawImage上,最后完成绘图。
为了将绘图过程在绘图过程中体现出来,我们一开始要将目标和辅助画板上的画布的颜色设置成和画板背景一样的颜色。这样每画一次就会把上次的绘图覆盖,实现其效果(将pictureBox作为aim的画板)。
效果就是这个样子滴!!!
bit = new Bitmap(pictureBox1.Width, pictureBox1.Height);
b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(bit);
g.FillRectangle(new SolidBrush(pictureBox1.BackColor), new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));//很重要
g.Dispose();
F = (Image)bit.Clone();//
O = (Image)bit.Clone();
aim = pictureBox1.CreateGraphics();
为了保存上一次绘图效果,我们先为辅助画板的画布O建一个副本img,保存img所画的,然后再将img上的内容画在F上,然后再将F上的内容画到目标画布O上。
代码如下:
public void Draw(MouseEventArgs e, string type)//绘图
{
Image img = (Image)O.Clone();
help = Graphics.FromImage(img);
help.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;//抗锯齿
switch (type)
{
case "矩形":
float width = Math.Abs(e.X - startp.X);//确定矩形的宽
float heigth = Math.Abs(e.Y - startp.Y);//确定矩形的高
PointF rectStartPointF = startp;
if (e.X < startp.X)
{
rectStartPointF.X = e.X;
}
if (e.Y < startp.Y)
{
rectStartPointF.Y = e.Y;
}
help.DrawRectangle(p, rectStartPointF.X, rectStartPointF.Y, width, heigth);
break;
case "椭圆":
help.DrawEllipse(p, startp.X, startp.Y, e.X - startp.X, e.Y - startp.Y);
break;
case "直线":
{//画直线
help.DrawLine(p, startp, new PointF(e.X, e.Y));
break;
}
case "实心矩形":
{
float w = Math.Abs(e.X - startp.X);//确定矩形的宽
float h = Math.Abs(e.Y - startp.Y);//确定矩形的高
PointF rectStartPointf = startp;
if (e.X < startp.X)
{
rectStartPointf.X = e.X;
}
if (e.Y < startp.Y)
{
rectStartPointf.Y = e.Y;
}
help.FillRectangle(new SolidBrush(color), rectStartPointf.X, rectStartPointf.Y, w, h);
break;
}
case "实心圆形":
{
help.FillEllipse(new SolidBrush(color), startp.X, startp.Y, e.X - startp.X, e.Y - startp.Y);
break;
}
case "笔":
{
//FontDialog ff = new FontDialog();
//ff.ShowDialog();
//f. = ff.;
help.DrawString(s,f,new SolidBrush(color),new PointF(e.X,e.Y));
break;
}
}
//help.FillPath();
help.Dispose();
help = Graphics.FromImage(F);
help.DrawImage(img, 0, 0);//原图覆盖
help.Dispose();
aim.DrawImage(img, 0, 0);
img.Dispose();
}
private void pic_MouseUp(object sender,MouseEventArgs e)
{
flag = false;
help = Graphics.FromImage(O);
help.DrawImage(F,0,0);
help.Dispose();
}
为了避免在改变窗口大小图形消失,我们要在PictureBox中Paint事件中添加如下代码:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(O,0,0);
}
源码 : 已上传至 GitHub:https://github.com/chp0304/Paint