• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
Lobooi
帮助1

项目目的

如标题所言,使用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();
        }
    }
}
学新通

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

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfkakf
系列文章
更多 icon
同类精品
更多 icon
继续加载