C# Windows Forms实现绘制画板

目录

[C# Windows Forms上绘制画板:](# Windows Forms上绘制画板:)

详细解释:

TempData临时数据,用来保存画笔相关的信息,如:颜色,大小,坐标等

类声明和成员变量

构造函数

文件菜单项点击事件

保存菜单项点击事件

画笔大小选择

颜色选择

清空画布

鼠标事件处理

完整代码:

总结

详细解释:

TempData临时数据,用来保存画笔相关的信息,如:颜色,大小,坐标等

复制代码
public static class TempData
{
    /// <summary>
    /// 用来保存上一次坐标点
    /// </summary>
    public static Point PrevPoint { get; set; }

    /// <summary>
    /// 画笔的颜色
    /// </summary>
    public static Color PenColor { get; set; } = Color.Black;

    /// <summary>
    /// 画笔的粗细
    /// </summary>
    public static int PenWidth { get; set; } = 2;

    
}

类声明和成员变量

  • Form1 类继承自 Form,表示一个Windows表单。

  • paintStart 是一个布尔变量,用于跟踪鼠标是否按下,从而开始绘图。

  • g 是一个 Graphics 对象,用于在窗体控件上绘制图像。

  • bmp 是一个 Bitmap 对象,用作绘图的画布。

    复制代码
    public partial class Form1 : Form
    {
        bool paintStart = false; // 标识是否开始绘画
        Graphics g = null; // 用于绘制图形的Graphics对象
        Bitmap bmp = null; // 用于存储绘制内容的Bitmap对象

构造函数

  • InitializeComponent 方法用于初始化窗体上的控件。

  • g 被初始化为 panel2Graphics 对象。

  • bmp 被初始化为一个与 panel2 控件大小相同的 Bitmap 对象。

    复制代码
    public Form1()
    {
        InitializeComponent();
        g = panel2.CreateGraphics();
        bmp = new Bitmap(panel2.Width, panel2.Height);
    }

文件菜单项点击事件

  • 打开一个文件对话框,让用户选择一个JPG图片文件。

  • 如果用户选择了文件并点击了OK,当前的 Bitmap 对象 bmp 被替换为用户选择的图片。

  • 使用 Graphics 对象 g 将新的 Bitmap 绘制到 panel2 上。

    复制代码
    private void 文件FToolStripMenuItem_Click(object sender, EventArgs e)
    {
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.Filter = "图片(*.jpg)|*.JPG";
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            bmp = new Bitmap(dlg.FileName);
            g.DrawImage(bmp, new Point(0, 0));
        }
    }

保存菜单项点击事件

  • 打开一个保存文件对话框,让用户选择保存路径和文件名。

  • 如果用户选择了路径并点击了OK,尝试将当前的 Bitmap 对象 bmp 保存为JPG图片。

  • 如果保存过程中发生异常(例如文件被其他程序占用),显示一个错误消息。

    复制代码
    private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
    {
        SaveFileDialog saveFileDialog = new SaveFileDialog();
        saveFileDialog.Filter = "图片(*.jpg)|*.JPG";
        if (saveFileDialog.ShowDialog() == DialogResult.OK)
        {
            try
            {
                bmp.Save(saveFileDialog.FileName);
            }
            catch (Exception)
            {
                MessageBox.Show("保存的文件名称,已经被独占打开!重新输入新文件名!");
            }
        }
    }

画笔大小选择

  • 这些方法设置画笔的大小,TempData.PenWidth 存储当前选择的画笔宽度。

    复制代码
    private void 小号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 2;
    }
    
    private void 中号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 6;
    }
    
    private void 大号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 10;
    }

颜色选择

  • 打开一个颜色对话框,让用户选择画笔的颜色。

  • 如果用户选择了颜色并点击了OK,将选择的颜色存储在 TempData.PenColor 中。清空画布

    复制代码
    private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        ColorDialog colorDialog = new ColorDialog();
        if (colorDialog.ShowDialog() == DialogResult.OK)
        {
            TempData.PenColor = colorDialog.Color;
        }
    }

清空画布

  • 显示一个确认对话框,询问用户是否确定要清空画布。

  • 如果用户点击"Yes",清空 panel2 的内容,重新创建一个空白的 Bitmap 对象,并将其绘制到 panel2 上。

    复制代码
    private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        DialogResult dr = MessageBox.Show("你确定要清空吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        if (dr == DialogResult.Yes)
        {
            g.Clear(Color.White);
            bmp = new Bitmap(panel2.Width, panel2.Height);
            g.DrawImage(bmp, new Point(0, 0));
        }
    }

鼠标事件处理

  • MouseDown: 当用户在 panel2 上按下鼠标左键时,设置 paintStarttrue 并记录当前鼠标位置。

  • MouseMove: 当用户在 panel2 上移动鼠标时,如果 paintStarttrue,则根据选择的工具(画笔或橡皮擦)绘制线条或擦除区域。

  • MouseUp: 当用户在 panel2 上释放鼠标左键时,设置 paintStartfalse,停止绘图。

    复制代码
    private void panel2_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            paintStart = true;
            TempData.PrevPoint = new Point(e.X, e.Y);
        }
    }
    
    private void panel2_MouseMove(object sender, MouseEventArgs e)
    {
        Graphics g2 = Graphics.FromImage(bmp);
        Pen pen = new Pen(TempData.PenColor, TempData.PenWidth);
        Point pt2 = new Point(e.X, e.Y);
        if (rbPen.Checked && paintStart)
        {
            g2.DrawLine(pen, TempData.PrevPoint, pt2);
            TempData.PrevPoint = pt2;
            g.DrawImage(bmp, 0, 0);
        }
        else if (rbEraser.Checked && paintStart)
        {
            g2.FillRectangle(new SolidBrush(panel2.BackColor), e.X, e.Y, TempData.PenWidth + 50, TempData.PenWidth + 50);
            g.DrawImage(bmp, 0, 0);
        }
    }
    
    private void panel2_MouseUp(object sender, MouseEventArgs e)
    {
        paintStart = false;
    }

完整代码:

复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace _2.画板
{
    public partial class Form1 : Form
    {
        // 标识,表示是否开始绘画
        bool paintStart = false;
        // 画板1(用panel2创建的,主要用来显示图)
        Graphics g = null;
        // 保存的图片  BitMap位图(.bmp), Image图片(.jpg,.jpeg,.png)
        Bitmap bmp = null;

        public Form1()
        {
            InitializeComponent();
            // 创建画板实例
            g = panel2.CreateGraphics();
            // 创建图片实例,设置宽高
            bmp = new Bitmap(panel2.Width, panel2.Height);
        }

        private void 文件FToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "图片(*.jpg)|*.JPG"; // 图片(*.jpg)|*.JPG|所有文件(*.*)|*.*
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                bmp = new Bitmap(dlg.FileName);
                g.DrawImage(bmp, new Point(0, 0));//重新绘制画板
            }
        }

        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "图片(*.jpg)|*.JPG";
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    bmp.Save(saveFileDialog.FileName);
                }
                catch (Exception)
                {
                    MessageBox.Show("保存的文件名称,已经被独占打开!重新输入新文件名!");
                }
            }
        }

        private void 小号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 2;
        }

        private void 中号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 6;
        }

        private void 大号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 10;
        }

        private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                TempData.PenColor = colorDialog.Color;
            }
        }

        private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("你确定要清空吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes)
            {
                g.Clear(Color.White); // 清空画板1
                bmp = new Bitmap(panel2.Width, panel2.Height); // 重新创建bmp实例,清空图片内容
                g.DrawImage(bmp, new Point(0, 0)); //用清空后的图片重新绘制画板1
            }
        }

        private void panel2_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                paintStart = true;

                // MouseEventArgs类型的实例中,拥有坐标系统
                // EventArgs
                TempData.PrevPoint = new Point(e.X, e.Y);
            }
        }

        private void panel2_MouseMove(object sender, MouseEventArgs e)
        {
            // 用空白图片bmp当成画板的底板,重新生成一个画板2,画板2上画的图其实是画在bmp。
            // 为什么要创建两个画板:画板1为了画图并显示。画板2为了保存绘制的图片,橡皮擦。
            // 两个画板上的图保持一致。
            Graphics g2 = Graphics.FromImage(bmp);

            Pen pen = new Pen(TempData.PenColor, TempData.PenWidth);
            Point pt2 = new Point(e.X, e.Y);
            if (rbPen.Checked && paintStart)
            {
                g2.DrawLine(pen, TempData.PrevPoint, pt2);
                TempData.PrevPoint = pt2;
                g.DrawImage(bmp, 0, 0); // 把bmp上的图,重新再绘制到画板1上展示出来。
            }
            else if (rbEraser.Checked && paintStart)
            {
                g2.FillRectangle(new SolidBrush(panel2.BackColor), e.X, e.Y, TempData.PenWidth + 50, TempData.PenWidth + 50);
                g.DrawImage(bmp, 0, 0);  // 为了同步g和g2两个画板。
            }
        }

        private void panel2_MouseUp(object sender, MouseEventArgs e)
        {
            paintStart = false;
        }
    }
}

总结

这个程序实现了一个基本的绘图工具,允许用户加载图片、保存图片、选择画笔大小和颜色,并在 panel2 控件上进行绘图。它通过处理鼠标事件来实现绘图功能,并通过 Graphics 对象在 Bitmap 上绘制,然后将 Bitmap 显示在 panel2 上。

相关推荐
阿杰同学1 分钟前
Java 设计模式 面试题及答案整理,最新面试题
java·开发语言·设计模式
这样の我1 分钟前
java 模拟chrome指纹 处理tls extension顺序
java·开发语言·chrome
yong99903 分钟前
基于MATLAB的雷达压制干扰仿真
开发语言·matlab
catchadmin14 分钟前
现代高效 PHP 开发的最佳实践
开发语言·后端·php
AnAnCode17 分钟前
【时间轮算法-实战】Java基于Netty的 `HashedWheelTimer`快速搭建时间轮算法系统
java·开发语言·算法·时间轮算法
liu****27 分钟前
12.C语言内存相关函数
c语言·开发语言·数据结构·c++·算法
曹牧1 小时前
C#:Dictionary类型数组
java·开发语言·c#
不秃头的帅哥1 小时前
程序地址空间(基于c++和linxu的一些个人笔记
linux·开发语言·c++·操作系统·内存空间
Dxxyyyy1 小时前
零基础学JAVA--Day41(IO文件流+IO流原理+InputStream+OutputStream)
java·开发语言·python
独自破碎E1 小时前
力场重叠问题
java·开发语言·算法