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里。
通过本实例了解如何在窗体上绘制各种图形,如矩形、椭圆、线条、文字等。运行效果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库