一、前言
上一节我们实现了在矩形与矩形之间添加连线,光是矩形太单调了,某些问题也暴露不出来,我们本节就来看一下,如何添加一个圆形,且支持圆形与圆形、圆形与矩形、矩形与矩形间的连线。在这个过程中我们会发现一些问题,这些问题我们后续课程会进行处理,大家也请带着自己的思考和理解去看。
相信看完的你,一定会有所收获!
本文地址:https://www.cnblogs.com/lesliexin/p/18923109
二、先看效果
我们先来看一下本节课整体要实现的效果,先有个整体印象。
特别说明一下,课程的编写是根据实际情况实时调整的,所以有时候与视频无法一一对应,像本篇教程,只需要看视频中的前半截就行,后半截视频的讲解在下节教课程中。
本节课程我们要依次实现两个效果:
绘制不同颜色颜色的、可拖动的圆形
连线支持圆形与圆形、圆形与矩形、矩形与矩形间连线
我们下面就来开始讲解。
三、实现效果1:添加不同颜色的、可拖动的圆形
有前面几节课程的基础,我们不需要过多的讲解,和矩形一样,只是在绘制时绘制成圆的,且拖动时要判断选的是圆形还是矩形。
我们下面就来看一下代码实操。
1,设计器界面
很简单的界面,就两个按钮:添加矩形、添加圆形
2,圆形定义
就像矩形的定义一样,我们也定义一个圆形的类,用来描述这个圆形:
我们注意到圆形核心也是一个Rectangle类型,这是因为GDI+在绘制圆形是需要的就是Rectangle,不过过多纠结:
因为整个界面我们要添加多个圆形,所以我们定义一个圆形集合:
在绘制时,依次绘制所有圆形:
3,鼠标点击事件
在鼠标点击时,我们这里就要多判断一步:点击的是圆形?还是矩形?
4,鼠标移动事件
在鼠标移动时,我们同样要判断当前点按着的是圆形还是矩形,并修改对应形状的位置。
5,添加圆形的方法
和添加矩形一样,往圆形集合中添加一个圆形:
好了,代码很简单,到此就实现了效果1,下面是完整的代码,大家试试吧。
点击查看代码- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace FlowChartDemo
- {
- public partial class FormDemo03V1 : FormBase
- {
- public FormDemo03V1()
- {
- InitializeComponent();
- DemoTitle = "第05节随课Demo Part1";
- DemoNote = "效果:支持添加圆形,支持不同颜色,支持拖动";
- }
- /// <summary>
- /// 矩形定义
- /// </summary>
- public class RectShape
- {
- /// <summary>
- /// 矩形ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 矩形位置和尺寸
- /// </summary>
- public Rectangle Rect { get; set; }
- }
- /// <summary>
- /// 圆形定义
- /// </summary>
- public class EllipseShape
- {
- /// <summary>
- /// 矩形ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 矩形位置和尺寸
- /// </summary>
- public Rectangle Rect { get; set; }
- }
- /// <summary>
- /// 直线连线定义
- /// </summary>
- public class LineLink
- {
- /// <summary>
- /// 连线ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 开始形状是否是矩形
- /// </summary>
- public bool StartShapeIsRect { get; set; }
- /// <summary>
- /// 结束开关是否是矩形
- /// </summary>
- public bool EndShapeIsRect { get; set; }
- /// <summary>
- /// 连线开始形状ID
- /// </summary>
- public string StartShapeId { get; set; }
- /// <summary>
- /// 连线结束形状ID
- /// </summary>
- public string EndShapeId { get; set; }
- }
- /// <summary>
- /// 矩形集合
- /// </summary>
- List<RectShape> RectShapes = new List<RectShape>();
- /// <summary>
- /// 圆形集合
- /// </summary>
- List<EllipseShape> EllipseShapes = new List<EllipseShape>();
- /// <summary>
- /// 当前界面连线集合
- /// </summary>
- List<LineLink> Links = new List<LineLink>();
- /// <summary>
- /// 画一个矩形(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="shape"></param>
- void DrawRectShape2(Graphics g, RectShape shape)
- {
- var index = RectShapes.FindIndex(a => a.Id == shape.Id);
- g.FillRectangle(GetBrush(index), shape.Rect);
- g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
- }
- /// <summary>
- /// 画一个圆形(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="shape"></param>
- void DrawEllipseShape2(Graphics g, EllipseShape shape)
- {
- var index = EllipseShapes.FindIndex(a => a.Id == shape.Id);
- g.FillEllipse(GetBrush(index), shape.Rect);
- g.DrawString(shape.Id, Font, Brushes.White, shape.Rect.X+20,shape.Rect.Y+20); //注:这里可以讲一下,要+20,是显示文本
- }
- /// <summary>
- /// 绘制一条连线(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="line"></param>
- void DrawLine2(Graphics g, LineLink line)
- {
- //通过连线的开始形状ID和结束形状ID,计算两个形状的中心点坐标
- var startPoint = line.StartShapeIsRect? GetCentertPointRect(line.StartShapeId):
- GetCentertPointEllipse(line.StartShapeId);
- var endPoint =line.EndShapeIsRect? GetCentertPointRect(line.EndShapeId) :
- GetCentertPointEllipse(line.EndShapeId);
- var index = Links.FindIndex(a => a.Id == line.Id);
- //绘制一条直线
- g.DrawLine(GetPen(index), startPoint, endPoint);
- }
- /// <summary>
- /// 重新绘制当前所有矩形和连线
- /// </summary>
- /// <param name="g"></param>
- void DrawAll(Graphics g)
- {
- g.Clear(panel1.BackColor);
- //绘制所有矩形
- foreach (var sp in RectShapes)
- {
- DrawRectShape2(g, sp);
- }
- //绘制所有圆形
- foreach (var sp in EllipseShapes)
- {
- DrawEllipseShape2(g, sp);
- }
- //绘制所有连线
- foreach (var ln in Links)
- {
- DrawLine2(g, ln);
- }
- }
- //注:文章中说明;此处不过于抽象,后续章节会有
- /// <summary>
- /// 当前是否有鼠标按下,且有矩形被选中
- /// </summary>
- bool _isMouseDown = false;
- /// <summary>
- /// 是否是矩形被选中,不是则是圆形
- /// </summary>
- bool _isRectMouseDown = true;
- /// <summary>
- /// 最后一次鼠标的位置
- /// </summary>
- Point _lastMouseLocation = Point.Empty;
- /// <summary>
- /// 当前被鼠标选中的矩形
- /// </summary>
- RectShape _selectedRectShape = null;
- /// <summary>
- /// 当前被鼠标选中的圆形
- /// </summary>
- EllipseShape _selectedEllipseShape = null;
- /// <summary>
- /// 获取不同的背景颜色
- /// </summary>
- /// <param name="i"></param>
- /// <returns></returns>
- Brush GetBrush(int i)
- {
- switch (i)
- {
- case 0: return Brushes.Red;
- case 1: return Brushes.Green;
- case 2: return Brushes.Blue;
- case 3: return Brushes.Orange;
- case 4: return Brushes.Purple;
- default: return Brushes.Red;
- }
- }
- /// <summary>
- /// 获取不同的画笔颜色
- /// </summary>
- /// <param name="i"></param>
- /// <returns></returns>
- Pen GetPen(int i)
- {
- return new Pen(GetBrush(i), 2);
- }
- /// <summary>
- /// 根据形状ID获取形状的中心点,以作为连线的起点或终点
- /// </summary>
- /// <param name="shapeId"></param>
- /// <returns></returns>
- Point GetCentertPointRect(string shapeId)
- {
- var sp = RectShapes.Find(a => a.Id == shapeId);
- if (sp != null)
- {
- var line1X = sp.Rect.X + sp.Rect.Width / 2;
- var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
- return new Point(line1X, line1Y);
- }
- return Point.Empty;
- }
- /// <summary>
- /// 根据形状ID获取形状的中心点,以作为连线的起点或终点
- /// </summary>
- /// <param name="shapeId"></param>
- /// <returns></returns>
- Point GetCentertPointEllipse(string shapeId)
- {
- var sp = EllipseShapes.Find(a => a.Id == shapeId);
- if (sp != null)
- {
- var line1X = sp.Rect.X + sp.Rect.Width / 2;
- var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
- return new Point(line1X, line1Y);
- }
- return Point.Empty;
- }
- private void toolStripButton1_Click(object sender, EventArgs e)
- {
- var rs = new RectShape()
- {
- Id = "矩形" + (RectShapes.Count + 1),
- Rect = new Rectangle()
- {
- X = 50,
- Y = 50,
- Width = 100,
- Height = 100,
- },
- };
- RectShapes.Add(rs);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- private void panel1_MouseDown(object sender, MouseEventArgs e)
- {
- //当鼠标按下时
- //取最上方的矩形,也就是最后添加的矩形
- var sp = RectShapes.FindLast(a => a.Rect.Contains(e.Location));
- //取最上方的圆形,也就是最后添加的圆形
- var ep = EllipseShapes.FindLast(a => a.Rect.Contains(e.Location));
- //注:说明,这里是简化情况,因为是两个LIST,无法判断序号,就先判断矩形
- //当前没有处理连线状态
- if (sp != null)
- {
- //设置状态及选中矩形
- _isMouseDown = true;
- _lastMouseLocation = e.Location;
- _selectedRectShape = sp;
- _selectedEllipseShape = null;
- _isRectMouseDown = true;
- }
- else if (ep != null)
- {
- //设置状态及选中圆形
- _isMouseDown = true;
- _lastMouseLocation = e.Location;
- _selectedRectShape = null;
- _selectedEllipseShape = ep;
- _isRectMouseDown = false;
- }
- }
- private void panel1_MouseMove(object sender, MouseEventArgs e)
- {
- if (_isMouseDown)
- {
- //当且仅当:有鼠标按下且有矩形被选中时,才进行后续操作
- //改变选中矩形的位置信息,随着鼠标移动而移动
- //计算鼠标位置变化信息
- var moveX = e.Location.X - _lastMouseLocation.X;
- var moveY = e.Location.Y - _lastMouseLocation.Y;
- //将选中形状的位置进行同样的变化
- if (_isRectMouseDown)
- {
- var oldXY = _selectedRectShape.Rect.Location;
- oldXY.Offset(moveX, moveY);
- _selectedRectShape.Rect = new Rectangle(oldXY, _selectedRectShape.Rect.Size);
- }
- else
- {
- var oldXY = _selectedEllipseShape.Rect.Location;
- oldXY.Offset(moveX, moveY);
- _selectedEllipseShape.Rect = new Rectangle(oldXY, _selectedEllipseShape.Rect.Size);
- }
- //记录当前鼠标位置
- _lastMouseLocation.Offset(moveX, moveY);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- }
- private void panel1_MouseUp(object sender, MouseEventArgs e)
- {
- //当鼠标松开时
- if (_isMouseDown)
- {
- //当且仅当:有鼠标按下且有矩形被选中时,才进行后续操作
- //重置相关记录信息
- _isMouseDown = false;
- _lastMouseLocation = Point.Empty;
- _selectedRectShape = null;
- _selectedEllipseShape = null;
- }
- }
- private void toolStripButton4_Click(object sender, EventArgs e)
- {
- var rs = new EllipseShape()
- {
- Id = "圆形" + (EllipseShapes.Count + 1),
- Rect = new Rectangle()
- {
- X = 50,
- Y = 50,
- Width = 100,
- Height = 100,
- },
- };
- EllipseShapes.Add(rs);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- }
- }
复制代码 四、实现效果2:连线支持圆形与圆形、圆形与矩形、矩形与矩形间连线
上一小节我们添加上了圆形,下面就来支持连线。
1,设计器界面
我们在上节的基础上稍做添加:
2,连线定义修改
因为我们要支持圆形与矩形间不同组合的连线,所以我们需要对连线定义进行扩展:
我们增加了两个布尔变量,来标识开始形状和结束形状是否是矩形,不是矩形则是圆形。
注:各位读者看到这里,可能会感觉很死板和繁琐。是的,确实如此。我们现在是刚开始起步,所以要从简入深,从繁化简,也是在这样一步步深入,我们明白了其中的痛点,引导着我们去调整、去优化。大概下下节课,我们就会使用抽象大法,到时一切都会变得优雅。
3,绘制连线
在绘制连线时,我们通过判断形状是圆形还是矩形,来取不同的中心点,并绘制连线。
注:当然,现在连线的是形状的圆心,所以并没有太大的区别。
4,鼠标点击事件
这部分不难理解但会比较繁琐,在判断是否连线时,还要判断开始形状与结束形状的类型等。
剩下的就和上一小节没多少差别了,不再赘述。下面是完整的代码,大家可以参照尝试。
点击查看代码- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace FlowChartDemo
- {
- public partial class FormDemo03V2 : FormBase
- {
- public FormDemo03V2()
- {
- InitializeComponent();
- DemoTitle = "第05节随课Demo Part2";
- DemoNote = "效果:支持矩形与矩形间连线、矩形与圆形间连线、圆形与圆形间连线";
- }
- /// <summary>
- /// 矩形定义
- /// </summary>
- public class RectShape
- {
- /// <summary>
- /// 矩形ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 矩形位置和尺寸
- /// </summary>
- public Rectangle Rect { get; set; }
- }
- /// <summary>
- /// 圆形定义
- /// </summary>
- public class EllipseShape
- {
- /// <summary>
- /// 矩形ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 矩形位置和尺寸
- /// </summary>
- public Rectangle Rect { get; set; }
- }
- /// <summary>
- /// 直线连线定义
- /// </summary>
- public class LineLink
- {
- /// <summary>
- /// 连线ID
- /// </summary>
- public string Id { get; set; }
- /// <summary>
- /// 开始形状是否是矩形
- /// </summary>
- public bool StartShapeIsRect { get; set; }
- /// <summary>
- /// 结束开关是否是矩形
- /// </summary>
- public bool EndShapeIsRect { get; set; }
- /// <summary>
- /// 连线开始形状ID
- /// </summary>
- public string StartShapeId { get; set; }
- /// <summary>
- /// 连线结束形状ID
- /// </summary>
- public string EndShapeId { get; set; }
- }
- /// <summary>
- /// 矩形集合
- /// </summary>
- List<RectShape> RectShapes = new List<RectShape>();
- /// <summary>
- /// 圆形集合
- /// </summary>
- List<EllipseShape> EllipseShapes = new List<EllipseShape>();
- /// <summary>
- /// 当前界面连线集合
- /// </summary>
- List<LineLink> Links = new List<LineLink>();
- /// <summary>
- /// 画一个矩形(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="shape"></param>
- void DrawRectShape2(Graphics g, RectShape shape)
- {
- var index = RectShapes.FindIndex(a => a.Id == shape.Id);
- g.FillRectangle(GetBrush(index), shape.Rect);
- g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
- }
- /// <summary>
- /// 画一个圆形(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="shape"></param>
- void DrawEllipseShape2(Graphics g, EllipseShape shape)
- {
- var index = EllipseShapes.FindIndex(a => a.Id == shape.Id);
- g.FillEllipse(GetBrush(index), shape.Rect);
- g.DrawString(shape.Id, Font, Brushes.White, shape.Rect.X+20,shape.Rect.Y+20); //注:这里可以讲一下,要+20,是显示文本
- }
- /// <summary>
- /// 绘制一条连线(不同颜色)
- /// </summary>
- /// <param name="g"></param>
- /// <param name="line"></param>
- void DrawLine2(Graphics g, LineLink line)
- {
- //通过连线的开始形状ID和结束形状ID,计算两个形状的中心点坐标
- var startPoint = line.StartShapeIsRect? GetCentertPointRect(line.StartShapeId): GetCentertPointEllipse(line.StartShapeId);
- var endPoint =line.EndShapeIsRect? GetCentertPointRect(line.EndShapeId) : GetCentertPointEllipse(line.EndShapeId);
- var index = Links.FindIndex(a => a.Id == line.Id);
- //绘制一条直线
- g.DrawLine(GetPen(index), startPoint, endPoint);
- }
- /// <summary>
- /// 重新绘制当前所有矩形和连线
- /// </summary>
- /// <param name="g"></param>
- void DrawAll(Graphics g)
- {
- g.Clear(panel1.BackColor);
- //绘制所有矩形
- foreach (var sp in RectShapes)
- {
- DrawRectShape2(g, sp);
- }
- //绘制所有圆形
- foreach (var sp in EllipseShapes)
- {
- DrawEllipseShape2(g, sp);
- }
- //绘制所有连线
- foreach (var ln in Links)
- {
- DrawLine2(g, ln);
- }
- }
- //注:文章中说明;此处不过于抽象,后续章节会有
- /// <summary>
- /// 当前是否有鼠标按下,且有矩形被选中
- /// </summary>
- bool _isMouseDown = false;
- /// <summary>
- /// 是否是矩形被选中,不是则是圆形
- /// </summary>
- bool _isRectMouseDown = true;
- /// <summary>
- /// 最后一次鼠标的位置
- /// </summary>
- Point _lastMouseLocation = Point.Empty;
- /// <summary>
- /// 当前被鼠标选中的矩形
- /// </summary>
- RectShape _selectedRectShape = null;
- /// <summary>
- /// 当前被鼠标选中的圆形
- /// </summary>
- EllipseShape _selectedEllipseShape = null;
- /// <summary>
- /// 添加连线时选中的第一个是否是矩形,不是则是圆形
- /// </summary>
- bool _selectedStartIsRect = true;
- /// <summary>
- /// 添加连线时选中的第一个矩形
- /// </summary>
- RectShape _selectedStartRectShape = null;
- /// <summary>
- /// 添加连线时选中的第一个圆形
- /// </summary>
- EllipseShape _selectedStartEllipseShape = null;
- /// <summary>
- /// 添加连线时选中的第二个是否是矩形,不是则是圆形
- /// </summary>
- bool _selectedEndIsRect = true;
- /// <summary>
- /// 添加连线时选中的第二个矩形
- /// </summary>
- RectShape _selectedEndRectShape = null;
- /// <summary>
- /// 添加连线时选中的第二个圆形
- /// </summary>
- EllipseShape _selectedEndEllipseShape = null;
- /// <summary>
- /// 是否正添加连线
- /// </summary>
- bool _isAddLink = false;
- /// <summary>
- /// 获取不同的背景颜色
- /// </summary>
- /// <param name="i"></param>
- /// <returns></returns>
- Brush GetBrush(int i)
- {
- switch (i)
- {
- case 0: return Brushes.Red;
- case 1: return Brushes.Green;
- case 2: return Brushes.Blue;
- case 3: return Brushes.Orange;
- case 4: return Brushes.Purple;
- default: return Brushes.Red;
- }
- }
- /// <summary>
- /// 获取不同的画笔颜色
- /// </summary>
- /// <param name="i"></param>
- /// <returns></returns>
- Pen GetPen(int i)
- {
- return new Pen(GetBrush(i), 2);
- }
- /// <summary>
- /// 根据形状ID获取形状的中心点,以作为连线的起点或终点
- /// </summary>
- /// <param name="shapeId"></param>
- /// <returns></returns>
- Point GetCentertPointRect(string shapeId)
- {
- var sp = RectShapes.Find(a => a.Id == shapeId);
- if (sp != null)
- {
- var line1X = sp.Rect.X + sp.Rect.Width / 2;
- var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
- return new Point(line1X, line1Y);
- }
- return Point.Empty;
- }
- /// <summary>
- /// 根据形状ID获取形状的中心点,以作为连线的起点或终点
- /// </summary>
- /// <param name="shapeId"></param>
- /// <returns></returns>
- Point GetCentertPointEllipse(string shapeId)
- {
- var sp = EllipseShapes.Find(a => a.Id == shapeId);
- if (sp != null)
- {
- var line1X = sp.Rect.X + sp.Rect.Width / 2;
- var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
- return new Point(line1X, line1Y);
- }
- return Point.Empty;
- }
- private void toolStripButton1_Click(object sender, EventArgs e)
- {
- var rs = new RectShape()
- {
- Id = "矩形" + (RectShapes.Count + 1),
- Rect = new Rectangle()
- {
- X = 50,
- Y = 50,
- Width = 100,
- Height = 100,
- },
- };
- RectShapes.Add(rs);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- private void panel1_MouseDown(object sender, MouseEventArgs e)
- {
- //当鼠标按下时
- //取最上方的矩形,也就是最后添加的矩形
- var sp = RectShapes.FindLast(a => a.Rect.Contains(e.Location));
- //取最上方的圆形,也就是最后添加的圆形
- var ep = EllipseShapes.FindLast(a => a.Rect.Contains(e.Location));
- if (!_isAddLink)
- {
- //注:说明,这里是简化情况,因为是两个LIST,无法判断序号,就先判断矩形
-
- //当前没有处理连线状态
- if (sp != null)
- {
- //设置状态及选中矩形
- _isMouseDown = true;
- _lastMouseLocation = e.Location;
- _selectedRectShape = sp;
- _selectedEllipseShape = null;
- _isRectMouseDown = true;
- }
- else if (ep != null)
- {
- //设置状态及选中圆形
- _isMouseDown = true;
- _lastMouseLocation = e.Location;
- _selectedRectShape = null;
- _selectedEllipseShape = ep;
- _isRectMouseDown = false;
- }
- }
- else
- {
- //正在添加连线
- if (_selectedStartRectShape == null && _selectedStartEllipseShape == null)
- {
- //证明没有矩形和圆形被选中则设置开始形状
- if (sp != null)
- {
- //设置开始形状是矩形
- _selectedStartRectShape = sp;
- _selectedStartEllipseShape = null;
- _selectedStartIsRect = true;
- }
- else if (ep != null)
- {
- //设置开始形状是圆形
- _selectedStartRectShape = null;
- _selectedStartEllipseShape = ep;
- _selectedStartIsRect = false;
- }
- toolStripStatusLabel1.Text = "请点击第2个形状";
- }
- else
- {
- //判断第2个形状是否是第1个形状
- if (sp != null)
- {
- //证明当前选中的是矩形
- if (_selectedStartRectShape != null)
- {
- //证明第1步选中的矩形
- //判断当前选中的矩形是否是第1步选中的矩形
- if (_selectedStartRectShape.Id == sp.Id)
- {
- toolStripStatusLabel1.Text = "不可选择同一个形状,请重新点击第2个形状";
- return;
- }
- }
- }
- else if (ep != null)
- {
- //证明当前选中的圆形
- if (_selectedStartEllipseShape != null)
- {
- //证明第1步选中的矩形
- //判断当前选中的矩形是否是第1步选中的矩形
- if (_selectedStartEllipseShape.Id == ep.Id)
- {
- toolStripStatusLabel1.Text = "不可选择同一个形状,请重新点击第2个形状";
- return;
- }
- }
- }
- //注:文章中说明:因为太过复杂,且不是本节重点,但不再进行去重判断
- if (sp != null)
- {
- //设置结束形状是矩形
- _selectedEndRectShape = sp;
- _selectedEndEllipseShape = null;
- _selectedEndIsRect = true;
- }
- else if (ep != null)
- {
- //设置结束形状是圆形
- _selectedEndRectShape = null;
- _selectedEndEllipseShape = ep;
- _selectedEndIsRect = false;
- }
- else
- {
- return;
- }
- //两个形状都设置了,便添加一条新连线
- Links.Add(new LineLink()
- {
- Id = "连线" + (Links.Count + 1),
- StartShapeId =_selectedStartIsRect? _selectedStartRectShape.Id:_selectedStartEllipseShape.Id,
- EndShapeId =_selectedEndIsRect? _selectedEndRectShape.Id:_selectedEndEllipseShape.Id,
- StartShapeIsRect=_selectedStartIsRect,
- EndShapeIsRect=_selectedEndIsRect,
- });
- //两个形状都已选择,结束添加连线状态
- _isAddLink = false;
- toolStripStatusLabel1.Text = "";
- //重绘以显示连线
- DrawAll(panel1.CreateGraphics());
- }
- }
- }
- private void panel1_MouseMove(object sender, MouseEventArgs e)
- {
- //当鼠标移动时
- //如果处于添加连线时,则不移动形状
- if (_isAddLink) return;
- if (_isMouseDown)
- {
- //当且仅当:有鼠标按下且有矩形被选中时,才进行后续操作
- //改变选中矩形的位置信息,随着鼠标移动而移动
- //计算鼠标位置变化信息
- var moveX = e.Location.X - _lastMouseLocation.X;
- var moveY = e.Location.Y - _lastMouseLocation.Y;
- //将选中形状的位置进行同样的变化
- if (_isRectMouseDown)
- {
- var oldXY = _selectedRectShape.Rect.Location;
- oldXY.Offset(moveX, moveY);
- _selectedRectShape.Rect = new Rectangle(oldXY, _selectedRectShape.Rect.Size);
- }
- else
- {
- var oldXY = _selectedEllipseShape.Rect.Location;
- oldXY.Offset(moveX, moveY);
- _selectedEllipseShape.Rect = new Rectangle(oldXY, _selectedEllipseShape.Rect.Size);
- }
- //记录当前鼠标位置
- _lastMouseLocation.Offset(moveX, moveY);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- }
- private void panel1_MouseUp(object sender, MouseEventArgs e)
- {
- //当鼠标松开时
- if (_isMouseDown)
- {
- //当且仅当:有鼠标按下且有矩形被选中时,才进行后续操作
- //重置相关记录信息
- _isMouseDown = false;
- _lastMouseLocation = Point.Empty;
- _selectedRectShape = null;
- _selectedEllipseShape = null;
- }
- }
- private void toolStripButton2_Click(object sender, EventArgs e)
- {
- _isAddLink = true;
- _selectedStartRectShape = null;
- _selectedEndRectShape = null;
- _selectedStartEllipseShape = null;
- _selectedEndEllipseShape = null;
- toolStripStatusLabel1.Text = "请点击第1个形状";
- }
- private void toolStripButton3_Click(object sender, EventArgs e)
- {
- _isAddLink = false;
- _selectedStartRectShape = null;
- _selectedEndRectShape = null;
- toolStripStatusLabel1.Text = "";
- DrawAll(panel1.CreateGraphics());
- }
- private void toolStripButton4_Click(object sender, EventArgs e)
- {
- var rs = new EllipseShape()
- {
- Id = "圆形" + (EllipseShapes.Count + 1),
- Rect = new Rectangle()
- {
- X = 50,
- Y = 50,
- Width = 100,
- Height = 100,
- },
- };
- EllipseShapes.Add(rs);
- //重绘所有矩形
- DrawAll(panel1.CreateGraphics());
- }
- }
- }
复制代码 五、结语
本一小节总体而言很简单,就是增加一个新的形状:圆形。但是在代码流程上却复杂很多,这也是我们后面课程使用抽象来优化的原因之一。
下节课我们就来到了显示效果优化部分了,除了显示质量外,还有拖动时闪烁的问题也会同步解决。敬请期待。
感谢大家的观看,本人水平有限,文章不足之处欢迎大家评论指正。
-[END]-
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |