c# GDI+简单绘图(二)

来源:互联网 发布:日本经典电影知乎 编辑:程序博客网 时间:2024/05/11 10:36

前几篇我已经向大家介绍了如何使用GDI+来绘图,并做了一个截图的实例,这篇我向大家介绍下如何来做一个类似windows画图的工具.

  个人认为如果想做一个功能强大的绘图工具,那么单纯掌握GDI还远远不够,我的目前也只能做一个比较简单的绘图工具了.不足之处,欢迎大家讨论!

  先来看一下最终效果吧:

 

 

主要实现功能:画直线,矩形,橡皮,圆形,切换颜色,打开图片,保存图片,清除图片,手动调节画布大小;软件刚启动时,为一张空白画布,我们可以直接在画布上绘画,也可以通过菜单中的“打开”,导入一张图片,然后我们就可以在这张图片上进行绘制。

  平台:VS2005 WINFORM

  由于代码过多,在这里只简要介绍下制作步骤,提供大家工程下载.

  1.对整个界面进行布局.

  2.实现绘图工具的功能

  3.实现颜色拾取的功能,这里我们直接拿上次写的自定义控件来用.

  4.实现菜单功能

  5.实现手动调节画布大小的功能

  6.测试

  实现绘图工具的功能

  为了让代码藕合度小点,稍许用了些设计模式,因为不是很会,所以代码还是有点乱乱的,嘿嘿!关于绘图工具的这些功能块全部写在了DrawTools这个类里.那么在主窗体中,只需要调用这个类来完成绘制就行了,而不需要过多的涉及到具体的绘图代码。绘图工具这个类提供的主要工具就是:铅笔、橡皮、直线、矩形、圆形、实心矩形、实心圆形。关于这些功能块的代码,并不难,只要大家对认真看过前几篇内容,那应该都看得懂。

  这里要注意以下几点:

1.如何防止记录不必要的绘图过程中的痕迹?

  这个问题在第三篇中有提到过,大家不妨先去看看那一篇。为了让代码看起来可读性高点,我设置了两个Image变量,finishingImg用来保存绘图过程中的痕迹,orginalImg用来保存已完成的绘图过程和初始时的背景图片。

  2.这个类如何与主窗体进行通信?

  当然如果直接将这些功能块写在主窗体中自然没有这个问题。但是那样代码会显得很混杂,如果只是工具代码出现问题就需要改整个项目。我在这里通过定义方法和属性,让主窗体通过给属性赋值将画板画布以及颜色什么的信息传给这个工具类,然后通过调用相应的工具方法来使用这些工具。

  3.关键属性

  要想让这些工具能正常使用,必须传递给他以下几样东西:目标画板(也就是picturebox),绘图颜色,原始画布。

  实现菜单功能


 

这里就需要我们对文件的操作有一点了解,大家可以去查一下相关资料。

  难点主要就是“打开”这个菜单项的实现

  我们要实现将打开后的图片在修改后重新保存就必须让文件在打开后就能关闭,否则就会因为文件打开而无法覆盖原文件。就会导致编译时弹出“GDI  一般性错误”。所以根据网上其它朋友的做法就是先将打开的图片通过GDI+将图片画到另一个画布上,然后及时关闭打开的图片和用来绘制该图片的画板。详见http://www.wanxin.org/redirect.php?tid=3&goto=lastpost

private void openPic_Click(object sender, EventArgs e)
    {
      OpenFileDialog ofd = new OpenFileDialog();//实例化文件打开对话框
      ofd.Filter = "JPG|*.jpg|Bmp|*.bmp|所有文件|*.*";//设置对话框打开文件的括展名
      if (ofd.ShowDialog() == DialogResult.OK)
      {
        Bitmap bmpformfile = new Bitmap(ofd.FileName);//获取打开的文件
        panel2.AutoScrollPosition = new Point(0,0);//将滚动条复位
        pbImg.Size = bmpformfile.Size;//调整绘图区大小为图片大小
        reSize.Location = new Point(bmpformfile.Width, bmpformfile.Height);//reSize为我用来实现手动调节画布大小用的
        //因为我们初始时的空白画布大小有限,"打开"操作可能引起画板大小改变,所以要将画板重新传入工具类
        dt.DrawTools_Graphics = pbImg.CreateGraphics();
        Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
        Graphics g = Graphics.FromImage(bmp);
        g.FillRectangle(new SolidBrush(pbImg.BackColor), new Rectangle(0, 0, pbImg.Width, pbImg.Height));//不使用这句话,那么这个bmp的背景就是透明的
        g.DrawImage(bmpformfile, 0, 0,bmpformfile.Width,bmpformfile.Height);//将图片画到画板上
        g.Dispose();//释放画板所占资源
        //不直接使用pbImg.Image = Image.FormFile(ofd.FileName)是因为这样会让图片一直处于打开状态,也就无法保存修改后的图片
        bmpformfile.Dispose();//释放图片所占资源
        g = pbImg.CreateGraphics();
        g.DrawImage(bmp, 0, 0);
        g.Dispose();
        dt.OrginalImg = bmp;
        bmp.Dispose();
        sFileName = ofd.FileName;//储存打开的图片文件的详细路径,用来稍后能覆盖这个文件
        ofd.Dispose();
      }
    }

 

原创粉丝点击