如标题所言,使用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());
}
////// 绘制直线
/// //////private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
m_draw.SetType(0);
RegisterForevents();
this.label1.Text = "按住鼠标左键移动画线";
}
////// 绘制矩形
/// //////private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
m_draw.SetType(1);
RegisterForevents();
this.label1.Text = "按住鼠标左键移动画矩形";
}
////// 绘制圆形
/// //////private void toolStripMenuItem3_Click(object sender, EventArgs e)
{
m_draw.SetType(2);
RegisterForevents();
this.label1.Text = "按住鼠标左键移动画圆";
}
////// 注册绘图鼠标事件
/// private void RegisterForevents()
{
if (drawIng == 0)
{
drawIng = 1;
this.panel3.Cursor = Cursors.Cross;
this.panel3.MouseDown += panel3_MouseDown;
this.panel3.MouseUp += panel3_MouseUp;
}
}
////// 鼠标按下
/// //////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;
}
}
////// 鼠标抬起
/// //////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);
}
}
////// 鼠标移动
/// //////private void panel3_MouseMove(object sender, MouseEventArgs e)
{
m_draw.DrawingCad(e.X, e.Y);
}
////// 清空
/// //////private void toolStripMenuItem4_Click(object sender, EventArgs e)
{
m_draw.ClearAll();
}
////// Esc结束绘制
/// //////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;
//图形数据
ListdrawData;
////// 初始化
/// ///画布public Draw(Graphics graphics)
{
this.graphics = graphics;
pen = new Pen(Color.Black, 1);
drawData = new List{ };
}
////// 初始化
/// ///画布///画笔颜色///画笔宽度public Draw(Graphics graphics,Color color, float width)
{
this.graphics = graphics;
pen = new Pen(color, width);
drawData = new List{ };
}
////// 设置绘图类型
/// ///绘图类型:0线,1矩形,2圆形public void SetType(float type)
{
this.type = type;
}
////// 全局数据绘制
/// 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);
}
}
////// 草图数据绘制
/// //////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);
}
}
////// 鼠标按下数据记录
/// ///X坐标///Y坐标public void MouseDownData(float x, float y)
{
drawData.Add(new float[] { type, x, y, x, y });
}
////// 鼠标抬起数据记录
/// ///X坐标///Y坐标public void MouseUpData(float x, float y)
{
drawData.Last()[3] = x;
drawData.Last()[4] = y;
//全局重绘
graphics.Clear(Color.White);
FullDrawing();
}
////// 清空画布
/// public void ClearAll()
{
graphics.Clear(Color.White);
drawData.Clear();
}
////// 结束绘制
/// public void CloseDraw()
{
//删除最后一条记录
drawData.RemoveAt(drawData.Count - 1);
//全局重绘
graphics.Clear(Color.White);
FullDrawing();
}
}
}
其中的逻辑关系比较简单,就不详细解释了,结束。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧