C# Winform画图

实验二:用winform实现画图

实验目的

构造属于你的专属画图程序,可参考系统自带的绘图板


环境

  1. 操作系统: Windows 10 X64
  2. IDE: visual studio 2017
  3. 语言:C#

界面布局及控件使用

  • 整个页面 :Panel
  • 文件菜单 :MenuStrip
  • 主页,查看菜单 :TabControl
  • 绘图板 :PictureBox
  • 控制绘图板大小 :PictureBox
  • 工具、图形按钮 :Button
  • 粗细 :Label
  • 实线虚线 :Label
  • 填充按钮 :Label
  • 功能模块分区 :Panel
  • 功能模块分区的名字 :Label
  • 颜色板 :自定义控件名为 userControl1
  • 左下角的实时坐标 :StatusStrip
  • 按钮的文本提示 : ToolTip

界面展示


Point1–画布画板

画布相当于一张纸,我们使用两张纸,一张originalimage用于保留最终绘图并贴在画板上;一张interimage用于保存中间绘图痕迹。
比如画一个矩形

  1. 画图前先将中间画布初始化为原始画布(去掉绘图痕迹)
  2. 将矩形画在在中间画布
  3. 在鼠标释放时将中间画布复制给原始画布
  4. 将原始画布贴到画板上

Point2–颜色板的实现

新建及使用
  1. 新建项目->选择visual C# ->Windows 桌面 ->Windows窗体控件库
  2. 完成编辑后,在项目文件中找到 bin文件下的后缀为.dll的文件拖拽进工具箱即可。
完成效果:

使用的控件:
  • 颜色按钮:Button
  • 编辑颜色按钮:ColorDialog
  • 颜色1,2面板:Panel
功能实现:
  1. 选择颜色,判断改变颜色1还是颜色2

      private void button_Click(object sender, EventArgs e)
    {
        Button currentButton = (Button)sender;
        currentLabel.BackColor = currentButton.BackColor; 
        if(currentLabel==label1)
        {
            label1.BackColor = currentButton.BackColor;
            color1 = currentButton.BackColor;
        }
        else
        {
            label7.BackColor = currentButton.BackColor;
            color2 = currentButton.BackColor;
        }
    }
    
  2. 颜色1颜色2切换
    方法:设置一个currentlabel指向当前颜色label

       private void color1_Click(object sender, EventArgs e)
     {
             currentLabel = label1;
         label3.BackColor = Color.PowderBlue;
         label4.BackColor = Color.Transparent;
     }
    
     private void color2_Click(object sender, EventArgs e)
     {
         currentLabel = label7;
         label4.BackColor = Color.PowderBlue;
         label3.BackColor = Color.Transparent;
     }
    
  3. colordialog 调用颜色对话框,并将颜色添加到可用按钮中
    重点:colorDialog1.ShowDialog()

     private void makecolor_Click(object sender, EventArgs e)
     {
    
         if (colorDialog1.ShowDialog() == DialogResult.OK)
         {
             Color mycolor = colorDialog1.Color;
    
             for (int i = 0; i < haveUse; i++)
             {
                 if (allButton[i].BackColor == mycolor)//与第i个重复,则从第i+1个到num-1个都向前移动一格
                 {
                     for (int k = i; k < NUM - 1; k++)
                     {
                         allButton[k].BackColor = allButton[k + 1].BackColor;
                     }
                     haveUse--;
                     break;
                 }
             }
    
             if (haveUse == NUM)//已经满了,前移一格
             {
                 for (int i = 0; i < NUM - 1; i++)
                 {
                     allButton[i] = allButton[i + 1];
                 }
                 allButton[NUM - 1].BackColor = mycolor;
                 haveUse++;
             }
             else//还没满
             {
                 allButton[haveUse].BackColor = mycolor;
                 allButton[haveUse].Enabled = true;
                 haveUse++;
             }
         }
     }
    

Point3–绘制图形

重点:绘制图形的函数

        //使用Graphics对象实现
         switch (type)
        {
            case "nonerh"://无填充菱形
                {
                    PointF[] pointFs = { new PointF(leftX + width / 2, leftY), new PointF(leftX, leftY + height / 2), new PointF(leftX + width / 2, leftY + height), new PointF(leftX + width, leftY + height / 2) };
                    interGraphics.DrawPolygon(mypen, pointFs);
                    break;
                }
            case "solidrh"://纯色菱形
                {
                    PointF[] pointFs = { new PointF(leftX + width / 2, leftY), new PointF(leftX, leftY + height / 2), new PointF(leftX + width / 2, leftY + height), new PointF(leftX + width, leftY + height / 2) };
                    interGraphics.FillPolygon(new SolidBrush(backcolor), pointFs);
                    interGraphics.DrawPolygon(mypen, pointFs);

                    break;
                }
            case "hatchrh"://圆点填充
                {
                    PointF[] pointFs = { new PointF(leftX + width / 2, leftY), new PointF(leftX, leftY + height / 2), new PointF(leftX + width / 2, leftY + height), new PointF(leftX + width, leftY + height / 2) };
                    interGraphics.FillPolygon(new HatchBrush(HatchStyle.LargeConfetti, backcolor, Color.White), pointFs);
                    interGraphics.DrawPolygon(mypen, pointFs);

                    break;
                }

            case "nonetriangle"://无填充等腰三角形
                {
                    PointF[] pointfs = { new PointF((startPoint.X + currentPoint.X) / 2, startPoint.Y), new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.DrawPolygon(mypen, pointfs);
                    break;
                }
            case "solidtriangle"://纯色填充等腰三角形
                {
                    PointF[] pointfs = { new PointF((startPoint.X + currentPoint.X) / 2, startPoint.Y), new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.FillPolygon(new SolidBrush(backcolor), pointfs);
                    interGraphics.DrawPolygon(mypen, pointfs);

                    break;
                }
            case "hatchtriangle"://圆点填充等腰三角形
                {
                    PointF[] pointfs = { new PointF((startPoint.X + currentPoint.X) / 2, startPoint.Y), new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.FillPolygon(new HatchBrush(HatchStyle.LargeConfetti, backcolor, Color.White), pointfs);
                    interGraphics.DrawPolygon(mypen, pointfs);

                    break;
                }
            case "nonetriangle2"://无填充直角三角形
                {
                    PointF[] pointfs = { startPoint, new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.DrawPolygon(mypen, pointfs);
                    break;
                }
            case "solidtriangle2"://纯色填充直角三角形
                {
                    PointF[] pointfs = { startPoint, new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.FillPolygon(new SolidBrush(backcolor), pointfs);
                    interGraphics.DrawPolygon(mypen, pointfs);

                    break;
                }
            case "hatchtriangle2"://圆点填充直角三角形
                {
                    PointF[] pointfs = {startPoint, new PointF(startPoint.X, currentPoint.Y), currentPoint };
                    interGraphics.FillPolygon(new HatchBrush(HatchStyle.LargeConfetti, backcolor, Color.White), pointfs);
                    interGraphics.DrawPolygon(mypen, pointfs);

                    break;
                }
            case "noneline"://直线
                interGraphics.DrawLine(mypen, startPoint, currentPoint);
                break;
            case "nonerectangle"://无填充矩形
                interGraphics.DrawRectangle(mypen, leftX, leftY, width, height);
                break;
            case "noneellipse"://无填充椭圆
                {               
                    interGraphics.DrawEllipse(mypen, leftX, leftY, width, height);
                    break;
                }
            case "nonearc"://弧线
                {                   
                    if (width != 0 && height != 0)
                        interGraphics.DrawArc(mypen, leftX, leftY, width, height, 0, 180);
                    break;
                }
            case "nonepie"://无填充饼形
                {
                   
                    if (width != 0 && height != 0)
                        interGraphics.DrawPie(mypen, leftX, leftY, width, height, 0, 180);
                    break;
                }
            case "solidrectangle"://纯色填充矩形
                {
                    
                    interGraphics.FillRectangle(new SolidBrush(backcolor), leftX, leftY, width, height);
                    interGraphics.DrawRectangle(mypen, leftX, leftY, width, height);
                    break;
                }
            case "solidellipse"://纯色填充椭圆
                {
                    interGraphics.FillEllipse(new SolidBrush(backcolor), leftX, leftY, width, height);
                    interGraphics.DrawEllipse(mypen, leftX, leftY, width, height);
                    break;
                }
            case "solidpie"://纯色填充饼形
                {
                    if (width != 0 && height != 0)
                    {
                        interGraphics.FillPie(new SolidBrush(backcolor), leftX, leftY, width, height, 0, 180);
                        interGraphics.DrawPie(mypen, leftX, leftY, width, height, 0, 180);
                    }
                    break;
                }
            case "hatchrectangle"://圆点填充矩形
                {
                    interGraphics.FillRectangle(new HatchBrush(HatchStyle.LargeConfetti,backcolor,Color.White), leftX, leftY, width, height);
                    interGraphics.DrawRectangle(mypen, leftX, leftY, width, height);
                    break;
                }
            case "hatchellipse"://圆点填充椭圆
                {
                    interGraphics.FillEllipse(new HatchBrush(HatchStyle.LargeConfetti,backcolor,Color.White), leftX, leftY, width, height);
                    interGraphics.DrawEllipse(mypen, leftX, leftY, width, height);
                    break;

                }
            case "hatchpie"://圆点填充饼形
                {
                    if (width != 0 && height != 0)
                    {
                        interGraphics.FillPie(new HatchBrush(HatchStyle.LargeConfetti, backcolor,Color.White), leftX, leftY, width, height, 0, 180);

                        interGraphics.DrawPie(mypen, leftX, leftY, width, height, 0, 180);
                    }
                    break;
                }
        }

Point4–铅笔

方法:使用DrawLine画线方法 从startpoint 到 currentpoint

    public void Pencile(MouseEventArgs e)//铅笔
    {
        PointF currentPoint = new PointF(e.X-10, e.Y+8);
        Graphics interGraphics = Graphics.FromImage(interImg);
        interGraphics.DrawLine(mypen, startPoint,currentPoint);
        originalImg = (Image)interImg.Clone();
        targetGraphics.DrawImage(originalImg,0,0);
        startPoint = currentPoint;
        
    }

Point5–橡皮

方法:相当于用纯色矩形覆盖,用DrwaRectangle方法

      public void Eraser(MouseEventArgs e)//橡皮擦
    {
        PointF currentPoint = new PointF(e.X, e.Y);
        Graphics interGraphics = Graphics.FromImage(interImg);
        interGraphics.FillRectangle(new SolidBrush(backcolor), startPoint.X-5,startPoint.Y-5,16,10);
        originalImg = (Image)interImg.Clone();
        targetGraphics.DrawImage(originalImg, 0, 0);
        startPoint = currentPoint;
    }

Point6–粗细、线条、填充

粗细:设置pen的Width属性

线条:设置pen的DashStyle属性。实现为Solid,虚线为Dot

填充:无填充:使用pen画;纯色填充:先用SolidBrush笔刷画,再用pen画上边;圆点填充:先用HatchBrush笔刷(设置属性HatchStyle.LargeConfetti)画,再用pen画上边


Point7–文本框

使用TextBox,点击绘图板,当绘图板里没有文本框时,显示文本框;有文本框时,移除文本框并将文本框的文字绘到绘图板上
重点:

  1. 动态添加控件:panel10.Controls.Add(mytb);(panel0为父容器)

  2. 动态删除控件:panel10.Controls.Remove(control);

  3. 绘制文字:interGraphics.DrawString(str, font, brush,pointF);
    font为字体样式,brush为字体填充笔刷,pointF为字体在父容器中的相对位置。

         if (drawtype == "text")
         {
             if (Extentionclass.FindControl(panel10, "mytb") == null)//第一次按下
             {
                 TextBox mytb = new TextBox();
                 mytb.Name = "mytb";
                 mytb.Location = new Point(e.X, e.Y+pictureBox1.Location.Y);//位置
                 mytb.BorderStyle = BorderStyle.FixedSingle;
                 panel10.Controls.Add(mytb);
                 //     panel10.Controls.SetChildIndex(mytb, 100);
                 mytb.BringToFront();
             }
             else
             {
                 Control control = Extentionclass.FindControl(panel10, "mytb");
                 string str =control.Text;
                 Font font = new Font("宋体", 9);
                 Brush brush = new SolidBrush(userControl11.Color1);
                 PointF pointF = new PointF(control.Location.X, control.Location.Y - pictureBox1.Location.Y);
                 panel10.Controls.Remove(control);
                 Graphics interGraphics = Graphics.FromImage(tool.InterImage);
                          
                 
                 interGraphics.DrawString(str, font, brush,pointF);
                 graphics.DrawImage(tool.InterImage, 0, 0);
             }
         }
    

Point8–新建文件、保存文件

新建文件之前要判断是否保存文件
用到的方法:

  1. 消息提示框:MessageBox.Show(“是否要保存文件”, “系统提示”, MessageBoxButtons.YesNoCancel);

  2. 保存、另存为、新建文件:如下代码

  3. 新建时要初始化绘画板

       private void 新建ToolStripMenuItem_Click(object sender, EventArgs e)
     {
        //是否保存
         DialogResult dialogResult = MessageBox.Show("是否要保存文件", "系统提示", MessageBoxButtons.YesNoCancel);
         if (dialogResult==DialogResult.Yes)//选择先保存
         {
             if (sFilename != null)//可以直接保存
             {
                 if (MessageBox.Show("是否要保存文件?", "系统提示", MessageBoxButtons.YesNo) == DialogResult.Yes)//选择yes保存
                 {
                     tool.OriginalImage.Save(sFilename);
                 }
             }
             else
             {
                 SaveFileDialog saveFile = new SaveFileDialog();
                 //            saveFile.FileName = "";
                 saveFile.Filter = "JPG|*.jpg;*.jpeg;*.jpe;*.jfif|GIF|*.gif|PNG|*.png|TIF|*.tif;*.tiff|ICO|*.ico|所有文件|*.*";
                 if (saveFile.ShowDialog() == DialogResult.OK)//文件夹显示成功
                 {
                     sFilename = saveFile.FileName;
                     tool.OriginalImage.Save(sFilename);
                 }
             }
         }
         else if(dialogResult==DialogResult.Cancel)//取消则什么都不做直接返回
         {
             return;
         }
         //
    
         //新建
         Bitmap  bmap= new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height);
         Graphics g = Graphics.FromImage(bmap);
         g.FillRectangle(new SolidBrush(Color.White), 0, 0, bmap.Width, bmap.Height);
         g.Dispose();
         tool.targetGraphics.DrawImage(bmap,0,0);
         tool.OriginalImage = bmap;
         bmap.Dispose();
     }
    

Point9–打开文件

打开之前要提示是否保存文件

        OpenFileDialog openFile = new OpenFileDialog();
        openFile.FileName = "";
        openFile.Filter = "JPG|*.jpg;*.jpeg;*.jpe;*.jfif|GIF|*.gif|PNG|*.png|TIF|*.tif;*.tiff|ICO|*.ico|所有文件|*.*";
        if (openFile.ShowDialog() == DialogResult.OK)//文件夹显示ok(成功)
        {
            if(openFile.FileName!="")
            {

               //插入是否保存代码

               Bitmap bitmap = new Bitmap(openFile.FileName);//从指定的文件初始化bitmap
                pictureBox1.Size = bitmap.Size;//调整绘图区大小为图片大小
                pictureBox3.Location = new Point(pictureBox1.Width, pictureBox1.Height + pictureBox1.Location.Y);
                //改变那个小角角的大小
                Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
                Graphics g = Graphics.FromImage(bm);
                g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
                g.DrawImage(bitmap, 0, 0);
                g.Dispose();

                tool.targetGraphics = pictureBox1.CreateGraphics();
                tool.targetGraphics.DrawImage(bm, 0, 0);
                tool.OriginalImage = bm;
                bitmap.Dispose();
                bm.Dispose();
                sFilename = openFile.FileName;
                openFile.Dispose();
          
            }
        }
    }

Point10–清除

方法:绘制一个和画板一样大小的白色矩形,注意要更新原始画布和中间画布

    private void 清除ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Bitmap newpic = new Bitmap(pictureBox1.Width,  pictureBox1.Height);
        Graphics g = Graphics.FromImage(newpic);
        g.FillRectangle(new SolidBrush(Color.White), 0, 0,pictureBox1.Width, pictureBox1.Height);
        g.Dispose();
        g = pictureBox1.CreateGraphics();
        g.DrawImage(newpic, 0, 0);
        g.Dispose();
        tool.OriginalImage = newpic;
    }

Point11–退出

点击Form右上角的关闭角标时调用Form1_FormClosing方法
点击菜单项的关闭选项时用this.close()
关闭前要提示是否保存


Point12–改变画板大小

改变画板大小通过画板右下角的一个小pictruebox(pb)实现。移动pb改变pb的位置,根据pb的相对于父容器的位置(即location)及画板的location得到画板的大小,改变画板大小后要改变初始画布和中间画布的大小,并将画布重新贴在画板上才能显示图案。

      private bool isResize = false;

    private void pictureBox3_MouseDown(object sender, MouseEventArgs e)
    {
        isResize = true;
    }

    private void pictureBox3_MouseMove(object sender, MouseEventArgs e)
    {
        if (isResize)
        {
            pictureBox3.Location = new Point(pictureBox3.Location.X + e.X, pictureBox3.Location.Y + e.Y);
        }
    }

    private void pictureBox3_MouseUp(object sender, MouseEventArgs e)
    {
        isResize = false;
        pictureBox1.Size = new Size(pictureBox3.Location.X-pictureBox1.Location.X, pictureBox3.Location.Y-pictureBox1.Location.Y);//改变大小

        tool.targetGraphics = pictureBox1.CreateGraphics();//再次设置
        Bitmap newBitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        Graphics tempGraphic = Graphics.FromImage(newBitmap);
        tempGraphic.FillRectangle(new SolidBrush(Color.White), 0, 0, pictureBox1.Width, pictureBox1.Height);//创建一张新的临时画纸
        tempGraphic.DrawImage(tool.OriginalImage, 0, 0);//将original画在上面
        tempGraphic.Dispose();

     //   graphics = pictureBox1.CreateGraphics();
        //tempGraphic =pictureBox1.CreateGraphics();
        //tempGraphic.DrawImage(newBitmap, 0, 0);
        //tempGraphic.Dispose();
      //  tool.targetGraphics.DrawImage(newBitmap, 0, 0);//--为什么不能重绘绘图板
        tool.OriginalImage = newBitmap;
        newBitmap.Dispose();

    }

知识点1——关于按钮图片的方法

右击解决方案里的项目->进入属性->找到左侧的资源->将图像导入其中->找到按钮的image属性导入图片

知识点2——设置坐标图标

进入该项目的项目文件夹->进入bin文件夹->进入debug文件夹->在debug文件夹中创建一个文件夹存放.ico或者.cur图片
相应代码如下:

pictureBox1.Cursor = new Cursor(Application.StartupPath + @"\img\pen.ico");

知识点3——绘图板重绘

在改变绘图板的大小,或者绘图板被覆盖之后要调用重绘绘图板方法才能显示图像

      private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.DrawImage(tool.OriginalImage, 0, 0);
    }

你可能感兴趣的:(C#)