Blueherb In solitude, where we are least alone

C#简单画图程序

实现过程:

(1) 新建窗体应用程序

(2) 添加一个MenuScrip控件;添加一个ToolScrip控件。

在ToolScrip控件中对每个单元,要将DisplayStyle属性改为Text

(3)程序代码。

1、新建菜单事件主要用白色清除窗体的背景,从而实现“文件新建”功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[csharp] view plain copy
private void 新建ToolStripMenuItem_Click(object sender, EventArgs e) 
      
          Graphics g = this.CreateGraphics(); 
          g.Clear(backColor); 
          toolStrip1.Enabled = true
          //创建一个Bitmap 
          theImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); 
          editFileName = "新建文件"
          //修改窗口标题 
          this.Text = "MyDraw\t" + editFileName; 
          ig = Graphics.FromImage(theImage); 
          ig.Clear(backColor); 
      

  2、打开事件用于打开“打开文件”对话框,并选择相应的图片,将图片绘制到窗体上.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[csharp] view plain copy
private void 打开ToolStripMenuItem_Click(object sender, EventArgs e) 
      
          openFileDialog1.Multiselect = false
          if (openFileDialog1.ShowDialog() == DialogResult.OK) 
          
              //修改窗口标题 
              this.Text = "MyDraw\t" + openFileDialog1.FileName; 
              editFileName = openFileDialog1.FileName; 
              theImage = Image.FromFile(openFileDialog1.FileName); 
              Graphics g = this.CreateGraphics(); 
              g.DrawImage(theImage, this.ClientRectangle); 
              ig = Graphics.FromImage(theImage); 
              ig.DrawImage(theImage, this.ClientRectangle); 
              //ToolBar可以使用了 
              toolStrip1.Enabled = true
          
      

  (3) 保存菜单项的Click事件用于将窗体背景保存为BMP格式的图片

1
2
3
4
5
6
7
8
9
10
11
12
[csharp] view plain copy
private void 保存ToolStripMenuItem_Click(object sender, EventArgs e) 
        
            saveFileDialog1.Filter = "图像(*.bmp)|*.bmp"
            saveFileDialog1.FileName = editFileName; 
            if (saveFileDialog1.ShowDialog() == DialogResult.OK) 
            
                theImage.Save(saveFileDialog1.FileName, ImageFormat.Bmp); 
                this.Text = "MyDraw\t" + saveFileDialog1.FileName; 
                editFileName = saveFileDialog1.FileName; 
            
        

  (4) 在Paint事件中将Image中保存的图像,绘制出来

1
2
3
4
5
6
7
8
9
10
11
[csharp] view plain copy
private void Form1_Paint(object sender, PaintEventArgs e) 
       
           //将Image中保存的图像,绘制出来 
           Graphics g = this.CreateGraphics(); 
           if (theImage != null
           
               g.Clear(Color.White); 
               g.DrawImage(theImage, this.ClientRectangle); 
           
       

  

(5)添加Frm_Text.cs文字输入框。

    添加一个Window窗体,取名为Frm_Text,然后对窗体的属性修改:

把FormBorderStyle属性改为 None;

把Modifiers的属性改为 Public

 

(6) 在窗体的MouseDown事件中,如果当前绘制的是字符串,在鼠标的当前位置显示文本框;如果绘制的是图开,设置图形的起始位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[cpp] view plain copy
private void Frm_Main_MouseDown(object sender, MouseEventArgs e) 
      
          if (e.Button == MouseButtons.Left) 
          
              //如果选择文字输入,则打开strInput窗体 
              if (drawTool == drawTools.String) 
              
                  Frm_Text inputBox = new Frm_Text(); 
                  inputBox.StartPosition = FormStartPosition.CenterParent; 
                  if (inputBox.ShowDialog() == DialogResult.OK) 
                  
                      Graphics g = this.CreateGraphics(); 
                      Font theFont = this.Font; 
                      g.DrawString(inputBox.textBox1.Text, theFont, new SolidBrush(foreColor), e.X, e.Y); 
                      ig.DrawString(inputBox.textBox1.Text, theFont, new SolidBrush(foreColor), e.X, e.Y); 
                  
              
              //如果开始绘制,则开始记录鼠标位置 
              else if ((isDrawing = !isDrawing) == true
              
                  startPoint = new Point(e.X, e.Y); 
                  oldPoint = new Point(e.X, e.Y); 
              
          
      

  (7) 在窗体的MouseMove 事件中,根据鼠标移动的大小绘制指定的图形.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
[cpp] view plain copy
private void Form1_MouseMove(object sender, MouseEventArgs e) 
    Graphics g; 
    g = this.CreateGraphics(); 
   
    if (isDrawing) 
    
        switch (drawTool) 
        
            case drawTools.None: 
                break
            case drawTools.Pen: 
                //从上一个点到当前点绘制线段 
                g.DrawLine(new Pen(foreColor, 1), oldPoint, new Point(e.X, e.Y)); 
                ig.DrawLine(new Pen(foreColor, 1), oldPoint, new Point(e.X, e.Y)); 
                oldPoint.X = e.X; 
                oldPoint.Y = e.Y; 
                break
            case drawTools.Line: 
                //首先恢复此次操作之前的图像,然后再添加Line 
                this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); 
                g.DrawLine(new Pen(foreColor, 1), startPoint, new Point(e.X, e.Y)); 
                break
            case drawTools.Ellipse: 
                //首先恢复此次操作之前的图像,然后再添加Ellipse 
                this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); 
                g.DrawEllipse(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); 
                break
            case drawTools.Rectangle: 
                //首先恢复此次操作之前的图像,然后再添加Rectangle 
                this.Frm_Main_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle)); 
                g.DrawRectangle(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); 
                break
            case drawTools.String: 
                break
            case drawTools.Rubber: 
                //用背景色绘制宽线段 
                g.DrawLine(new Pen(backColor, 20), oldPoint, new Point(e.X, e.Y)); 
                ig.DrawLine(new Pen(backColor, 20), oldPoint, new Point(e.X, e.Y)); 
                oldPoint.X = e.X; 
                oldPoint.Y = e.Y; 
                break
        
    

  (8) 在窗体的MouseUp事件中,根据用户选择的画笔,绘制直线,椭圆或矩形等指定图形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[csharp] view plain copy
private void Form1_MouseUp(object sender, MouseEventArgs e) 
        
            isDrawing = false
            switch (drawTool) 
            
                case drawTools.Line: 
                    ig.DrawLine(new Pen(foreColor, 1), startPoint, new Point(e.X, e.Y)); 
                    break
                case drawTools.Ellipse: 
                    ig.DrawEllipse(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); 
                    break
                case drawTools.Rectangle: 
                    ig.DrawRectangle(new Pen(foreColor, 1), startPoint.X, startPoint.Y, e.X - startPoint.X, e.Y - startPoint.Y); 
                    break
            
        

  

=============================================================================================================

这里解释为什么在拉直线时线会跟着鼠标动,而用选择画笔时移动鼠标就会画出线。

这里有两个Graphics:

(1) 真实的场景graphics.   它它上面画出的画面就是我个看到的画面。

     eg:

               private void Form1_Paint(object sender, PaintEventArgs e)
             {
                     //将Image中保存的图像,绘制出来
                      Graphics g = this.CreateGraphics();

(2)做为临时存储用的Graphic.

它在新建的时候创建:

1
2
3
4
5
6
7
8
[csharp] view plain copy
//创建一个Bitmap 
           theImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); 
           editFileName = "新建文件"
           //修改窗口标题 
           this.Text = "MyDraw\t" + editFileName; 
           ig = Graphics.FromImage(theImage); 
           ig.Clear(backColor); 

  显示出来: 把theImage显示出来就是把以前保存在ig里的东西显示出来了

1
2
3
4
5
6
7
8
9
10
11
[csharp] view plain copy
private void Frm_Main_Paint(object sender, PaintEventArgs e) 
       
           //将Image中保存的图像,绘制出来 
           Graphics g = this.CreateGraphics(); 
           if (theImage != null
           
               g.Clear(Color.White); 
               g.DrawImage(theImage, this.ClientRectangle); 
           
       

  

在Form1_MouseMove里

如果是画笔,那么把图像保存到了两个graphic中,这样我们可以看到移动的画,最后也将显示所有画。

如果直线或矩形,那么只先画到第一个graphics里,在鼠标放开时才画到第二个graphic里。

 

通过本实例了解如何在窗体上绘制各种图形,如矩形、椭圆、线条、文字等。运行效果如下:

posted @   孤燕  阅读(22231)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
 
点击右上角即可分享
微信分享提示