用System.Drawing类实现的绘制直线、矩形、圆形的方法。

项目目的

如标题所言,使用System.Drawing类来实现简单图形的绘制,这个项目使用C#语言进行winform窗体应用开发,主要功能有:绘制直线、绘制矩形、绘制圆形、ESC结束绘制、清空画布。

窗体设计

窗体设计如下图所示:主要分成三个部分四个区域对窗体进行设计(窗体的控制代码放在最后)。
绘图主窗体

功能实现

自定义绘制类(绘制类代码放在最后),包括绘制方法、鼠标事件、按键事件等方法的具体实现,绘制方法集成直线、矩形、圆形的绘制代码,鼠标事件包括按下事件、抬起事件、移动事件,按键事件只有ESC结束绘制。

1.绘制方法

绘制方法需要设定画布Graphics、画笔Pen等内容,并通过DrawLine()DrawRectangle()DrawEllipse()实现画直线、矩形、圆形。如下代码所示:

	Pen pen = new Pen(Color.Black, 1);//实例化画笔
	Graphics graphics = this.panel3.CreateGraphics();//基于绘图区Panel3创建画布
	……
	graphics.DrawLine(Pen pen, float x1, float y1, float x2, float y2);//基于起止点的坐标绘制直线
	graphics.DrawRectangle(Pen pen, float x, float y, float width, float height);//基于点的坐标和长宽绘制矩形
	graphics.DrawEllipse(Pen pen, float x, float y, float width, float height);//基于点的坐标和长宽绘制圆形

但是上面的绘图方法在直接调用时,绘制矩形和圆形都有一定的局限。绘制矩形只能从左上角进行绘制,绘制圆形时只能通过外接矩形进行绘制(在类方法元数据中有说明,可自行查看),不符合我们实际绘图的需求,因此需要对方法的进行一点修正。具体如下

	//绘制矩形
	float px, py, width, height;
	px = Math.Min(float x1, float x2);//获取一下矩形最左上角的坐标位置
	py = Math.Min(float y1, float y2);
	width = Math.Abs(float x1 - float x2);//长宽的计算不变
	height = Math.Abs(float y1 - float y2);
	graphics.DrawRectangle(pen, px, py, width, height);//可以任意方向绘制矩形
	……
	//绘制圆形
	float r, rx, ry, rw, rh;
    r = (float)Math.Sqrt((float x1 - float x2) * (float x1 - float x2) + (float y1 - float y2) * (float y1 - float y2));//计算半径
    rx = item[1] - r;//计算外接矩形最左上角坐标
    ry = item[2] - r;
    rw = r + r;//计算长宽
    rh = r + r;
    graphics.DrawEllipse(pen, rx, ry, rw, rh);//通过圆心加半径绘制圆形

2.鼠标事件

鼠标事件主要是按下MouseDown、抬起MouseUp、移动MouseMove三个事件,当鼠标按下时记录起点坐标,鼠标按住不松移动时记录路径点坐标、鼠标松开抬起时记录结束点坐标;在这其中,鼠标按下、抬起负责对结果数据的记录,鼠标移动负责对过程数据的记录并中间过程图形。他们之间具有一定逻辑关系,如下代码所示:

	// 鼠标按下
	private void panel3_MouseDown(object sender, MouseEventArgs e)
	{
		m_draw.MouseDownData(e.X, e.Y);//记录起点数据
		this.panel3.MouseMove += panel3_MouseMove;//注册鼠标移动事件
	}
	
	// 鼠标抬起
	private void panel3_MouseUp(object sender, MouseEventArgs e)
	{
		this.panel3.MouseMove -= panel3_MouseMove;//取消册鼠标移动事件
		m_draw.MouseUpData(e.X, e.Y);//记录结果数据
	}
	
	// 鼠标移动
	private void panel3_MouseMove(object sender, MouseEventArgs e)
	{
	    m_draw.DrawingCad(e.X, e.Y);//鼠标移动路径点数据并绘制草图
	}

3.其他方法

1.ESC结束绘制的事件,直接看代码:

	/// Esc结束绘制
    private void DrawForm_KeyPress(object sender, KeyPressEventArgs e)
    {
		if (e.KeyChar == (char)27)//判断是否按下ESC键
        {
        this.panel3.MouseDown -= panel3_MouseDown;//取消各类事件
        this.panel3.MouseUp -= panel3_MouseUp;
        this.panel3.MouseMove -= panel3_MouseMove;

        if (drawIng == 2)//drawIng 判断绘制状态
        	{
            drawIng = 0;
            m_draw.CloseDraw();//实现结束后的绘图
        	}
        }
    }

2.清空方法,清空很简单,使用Clear(),用白色进行清空,如下:

	graphics.Clear(Color.White);

功能演示

看下面视频:

绘图演示

完整代码

主窗体代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HuiTu
{
    public partial class DrawForm : Form
    {
        //实例化绘图类
        Draw m_draw;
        //绘图状态(0没有绘制,1等待绘制,2正在绘制)
        int drawIng;
        public DrawForm()
        {
            InitializeComponent();

            drawIng = 0;
            m_draw = new Draw(this.panel3.CreateGraphics());
        }

        /// <summary>
        /// 绘制直线
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            m_draw.SetType(0);

            RegisterForevents();

            this.label1.Text = "按住鼠标左键移动画线";

        }
        /// <summary>
        /// 绘制矩形
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            m_draw.SetType(1);

            RegisterForevents();

            this.label1.Text = "按住鼠标左键移动画矩形";
        }
        /// <summary>
        /// 绘制圆形
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            m_draw.SetType(2);

            RegisterForevents();

            this.label1.Text = "按住鼠标左键移动画圆";
        }
        /// <summary>
        /// 注册绘图鼠标事件
        /// </summary>
        private void RegisterForevents()
        {
            if (drawIng == 0)
            {
                drawIng = 1;
                this.panel3.Cursor = Cursors.Cross;
                this.panel3.MouseDown += panel3_MouseDown;
                this.panel3.MouseUp += panel3_MouseUp;
            }
        }
        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel3_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                drawIng = 2;
                m_draw.MouseDownData(e.X, e.Y);
                this.panel3.MouseMove += panel3_MouseMove;
            }
        }
        /// <summary>
        /// 鼠标抬起
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel3_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                drawIng = 1;
                this.panel3.MouseMove -= panel3_MouseMove;
                m_draw.MouseUpData(e.X, e.Y);
            }  
        }
        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel3_MouseMove(object sender, MouseEventArgs e)
        {
            m_draw.DrawingCad(e.X, e.Y);
        }
        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            m_draw.ClearAll();
        }
        /// <summary>
        /// Esc结束绘制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DrawForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)27)
            {
                this.panel3.Cursor = Cursors.Default;
                this.panel3.MouseDown -= panel3_MouseDown;
                this.panel3.MouseUp -= panel3_MouseUp;
                this.panel3.MouseMove -= panel3_MouseMove;

                if (drawIng == 2)
                {
                    drawIng = 0;
                    m_draw.CloseDraw();
                }
            }
        }
    }
}

绘图类代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HuiTu
{
    class Draw
    {
        //画笔、画布
        Pen pen;
        Graphics graphics;
        //绘图类型
        float type;
        //图形数据
        List<float[]> drawData;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="graphics">画布</param>
        public Draw(Graphics graphics)
        {
            this.graphics = graphics;
            pen = new Pen(Color.Black, 1);
            drawData = new List<float[]> { };
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="graphics">画布</param>
        /// <param name="color">画笔颜色</param>
        /// <param name="width">画笔宽度</param>
        public Draw(Graphics graphics,Color color, float width)
        {
            this.graphics = graphics;
            pen = new Pen(color, width);
            drawData = new List<float[]> { };
        }
        /// <summary>
        /// 设置绘图类型
        /// </summary>
        /// <param name="type">绘图类型:0线,1矩形,2圆形</param>
        public void SetType(float type)
        {
            this.type = type;
        }
        /// <summary>
        /// 全局数据绘制
        /// </summary>
        private void FullDrawing()
        {
            try
            {
                foreach (var item in drawData)
                {
                    switch (item[0])
                    {
                        case 0:
                            graphics.DrawLine(pen, item[1], item[2], item[3], item[4]);
                            break;
                        case 1:
                            float px, py, width, height;
                            px = Math.Min(item[1], item[3]);
                            py = Math.Min(item[2], item[4]);
                            width = Math.Abs(item[1] - item[3]);
                            height = Math.Abs(item[2] - item[4]);
                            graphics.DrawRectangle(pen, px, py, width, height);
                            break;
                        case 2:
                            float r, rx, ry, rw, rh;
                            r = (float)Math.Sqrt((item[1] - item[3]) * (item[1] - item[3]) + (item[2] - item[4]) * (item[2] - item[4]));
                            rx = item[1] - r;
                            ry = item[2] - r;
                            rw = r + r;
                            rh = r + r;
                            graphics.DrawEllipse(pen, rx, ry, rw, rh);
                            break;
                        default:
                            MessageBox.Show("数据有误!", "警告");
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);  
            }
        }
        /// <summary>
        /// 草图数据绘制
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void DrawingCad(float x, float y)
        {
            try
            {
                graphics.Clear(Color.White);
                FullDrawing();
                float[] cadPos = drawData.Last();
                switch (cadPos[0])
                {
                    case 0:
                        graphics.DrawLine(pen, cadPos[1], cadPos[2], x, y);
                        break;
                    case 1:
                        float px, py, width, height;
                        px = Math.Min(cadPos[1], x);
                        py = Math.Min(cadPos[2], y);
                        width = Math.Abs(cadPos[1] - x);
                        height = Math.Abs(cadPos[2] - y);
                        graphics.DrawRectangle(pen, px, py, width, height);
                        break;
                    case 2:
                        float r, rx, ry, rw, rh;
                        r = (float)Math.Sqrt((cadPos[1] - x) * (cadPos[1] - x) + (cadPos[2] - y) * (cadPos[2] - y));
                        rx = cadPos[1] - r;
                        ry = cadPos[2] - r;
                        rw = r + r;
                        rh = r + r;
                        graphics.DrawLine(pen, cadPos[1], cadPos[2], x, y);
                        graphics.DrawEllipse(pen, rx, ry, rw, rh);
                        break;
                    default:
                        MessageBox.Show("数据有误!", "警告");
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// 鼠标按下数据记录
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        public void MouseDownData(float x, float y)
        {
            drawData.Add(new float[] { type, x, y, x, y });
        }
        /// <summary>
        /// 鼠标抬起数据记录
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        public void MouseUpData(float x, float y)
        {
            drawData.Last()[3] = x;
            drawData.Last()[4] = y;
            //全局重绘
            graphics.Clear(Color.White);
            FullDrawing();
        }
        /// <summary>
        /// 清空画布
        /// </summary>
        public void ClearAll()
        {
            graphics.Clear(Color.White);
            drawData.Clear();
        }
        /// <summary>
        /// 结束绘制
        /// </summary>
        public void CloseDraw()
        {
            //删除最后一条记录
            drawData.RemoveAt(drawData.Count - 1);
            //全局重绘
            graphics.Clear(Color.White);
            FullDrawing();
        }
    }
}

其中的逻辑关系比较简单,就不详细解释了,结束。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值