| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using System.Linq;
- namespace HySoft.FlowEditor
- {
- public partial class FlowBrokenLineControl : UserControl
- {
- #region 字段
- /// <summary>
- /// 线宽
- /// </summary>
- int _lineWidth = 2;
- /// <summary>
- /// 线半宽
- /// </summary>
- int _lineHalfWidth = 1;
- /// <summary>
- /// 图形路径
- /// </summary>
- GraphicsPath _graphicsPath;
- /// <summary>
- /// 折线点
- /// </summary>
- List<Point> _points;
- /// <summary>
- /// 线颜色
- /// </summary>
- Color _lineColor;
- /// <summary>
- /// 被选中时的线颜色
- /// </summary>
- Color _selectedLineColor;
- /// <summary>
- /// 是否有箭头
- /// </summary>
- bool _bArrow = true;
- /// <summary>
- /// 绑定的线对象
- /// </summary>
- FlowLine _flowLine;
- /// <summary>
- /// 是否被选中
- /// </summary>
- bool _bSelected;
- #endregion
- #region 属性
- /// <summary>
- /// 折线组成的点的列表
- /// </summary>
- public List<Point> PointList
- {
- get { return _points; }
- set
- {
- _points = value;
- SetControlRegion();
- }
- }
- /// <summary>
- /// 线颜色
- /// </summary>
- public Color LineColor
- {
- get { return _lineColor; }
- set
- {
- _lineColor = value;
- if (!_bSelected)
- BackColor = _lineColor;
- }
- }
- /// <summary>
- /// 被选中时的线颜色
- /// </summary>
- public Color SelectedLineColor
- {
- get { return _selectedLineColor; }
- set
- {
- _selectedLineColor = value;
- if (_bSelected)
- BackColor = _lineColor;
- }
- }
- /// <summary>
- /// 是否被选中
- /// </summary>
- public bool BeSelected
- {
- get { return _bSelected; }
- set
- {
- if (_bSelected != value)
- {
- _bSelected = value;
- if (_bSelected)
- BackColor = _selectedLineColor;
- else
- BackColor = _lineColor;
- }
- }
- }
- /// <summary>
- /// 线宽
- /// </summary>
- public int LineWidth
- {
- get { return _lineWidth; }
- set
- {
- if(value < 2)
- _lineWidth = 2;
- else
- _lineWidth = value;
- _lineHalfWidth = (_lineWidth + 1) / 2;
- SetControlRegion();
- }
- }
- /// <summary>
- /// 绑定的线对象
- /// </summary>
- public FlowLine FlowLine
- {
- get { return _flowLine; }
- set { _flowLine = value; }
- }
- #endregion
- #region 公开方法
- /// <summary>
- /// 构造方法
- /// </summary>
- public FlowBrokenLineControl()
- {
- InitializeComponent();
-
- this.BackColor = _lineColor;
- this.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.ResumeLayout(false);
- }
- /// <summary>
- /// 构造方法
- /// </summary>
- /// <param name="line">绑定的线</param>
- public FlowBrokenLineControl(FlowLine line)
- {
- InitializeComponent();
- _flowLine = line;
- this.BackColor = _lineColor;
- this.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.ResumeLayout(false);
- }
- #endregion
- #region 私有方法
- /// <summary>
- /// 重新设置控件的GraphicsPath
- /// </summary>
- void ResetControlGraphicsPath()
- {
- _graphicsPath = GetGraphicsPath();
- }
- /// <summary>
- /// (废弃的)获取GraphicsPath
- /// </summary>
- /// <returns></returns>
- GraphicsPath OldGetGraphicsPath()
- {
- ///计算points
- if (_points == null || _points.Count < 2)
- return null;
- Point[] points = new Point[_points.Count * 2];
- //计算第一个点
- TwoPointPos begainTwoPointPos = GetTwoPointPos(_points[0], _points[1]);
- switch (begainTwoPointPos)
- {
- case TwoPointPos.Down:
- case TwoPointPos.Up:
- points[0] = new Point(_points[0].X - _lineHalfWidth, _points[0].Y);
- points[_points.Count * 2 - 1] = new Point(_points[0].X + _lineHalfWidth, _points[0].Y);
- break;
- case TwoPointPos.Left:
- case TwoPointPos.Right:
- points[0] = new Point(_points[0].X, _points[0].Y - _lineHalfWidth);
- points[_points.Count * 2 - 1] = new Point(_points[0].X, _points[0].Y + _lineHalfWidth);
- break;
- }
- //计算中间点
- int i = 0;
- for (; i < _points.Count - 2; i++)
- {
- ThreePointPos threePointPos = GetThreePointPos(_points[i], _points[i + 1], _points[i + 2]);
- switch (threePointPos)
- {
- case ThreePointPos.Down:
- case ThreePointPos.Up:
- points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y);
- points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y);
- break;
- case ThreePointPos.Left:
- case ThreePointPos.Right:
- points[i + 1] = new Point(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth);
- points[points.Length - i - 2] = new Point(_points[i + 1].X, _points[i + 1].Y + _lineHalfWidth);
- break;
- case ThreePointPos.UpRight:
- case ThreePointPos.DownLeft:
- case ThreePointPos.RightUp:
- case ThreePointPos.LeftDown:
- points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y - _lineHalfWidth);
- points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y + _lineHalfWidth);
- break;
- case ThreePointPos.UpLeft:
- case ThreePointPos.DownRight:
- case ThreePointPos.LeftUp:
- case ThreePointPos.RightDown:
- points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y + _lineHalfWidth);
- points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y - _lineHalfWidth);
- break;
- }
- }
- //计算最后一个点
- TwoPointPos endTwoPointPos = GetTwoPointPos(_points[_points.Count - 2], _points[_points.Count - 1]);
- switch (endTwoPointPos)
- {
- case TwoPointPos.Down:
- case TwoPointPos.Up:
- points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y);
- points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y);
- break;
- case TwoPointPos.Left:
- case TwoPointPos.Right:
- points[i + 1] = new Point(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth);
- points[points.Length - i - 2] = new Point(_points[i + 1].X, _points[i + 1].Y + _lineHalfWidth);
- break;
- }
- //计算types
- if (points == null && points.Length <= 2)
- return null;
- Byte[] types = new Byte[points.Length];
- for (int j = 0; j < types.Length; j++)
- {
- types[j] = (Byte)PathPointType.Line;
- }
- System.Drawing.Drawing2D.GraphicsPath path = new GraphicsPath(points, types);
- return path;
- }
- /// <summary>
- /// 获取GraphicsPath
- /// </summary>
- /// <returns></returns>
- GraphicsPath GetGraphicsPath()
- {
- ///计算points
- if (_points == null || _points.Count < 2)
- return null;
- Rectangle[] rects = new Rectangle[_points.Count - 1];
- for (int i = 0; i < _points.Count - 1; i++)
- {
- rects[i] = new Rectangle();
- TwoPointPos twoPointPos = GetTwoPointPos(_points[i], _points[i+1]);
- switch (twoPointPos)
- {
- case TwoPointPos.Up:
- rects[i] = new Rectangle(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y, _lineHalfWidth * 2, _points[i].Y - _points[i + 1].Y);
- break;
- case TwoPointPos.Down:
- rects[i] = new Rectangle(_points[i].X - _lineHalfWidth, _points[i].Y, _lineHalfWidth * 2, _points[i + 1].Y - _points[i].Y);
- break;
- case TwoPointPos.Left:
- rects[i] = new Rectangle(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth, _points[i].X - _points[i + 1].X, _lineHalfWidth * 2);
- break;
- case TwoPointPos.Right:
- rects[i] = new Rectangle(_points[i].X, _points[i + 1].Y - _lineHalfWidth, _points[i + 1].X - _points[i].X, _lineHalfWidth * 2);
- break;
- }
- }
- System.Drawing.Drawing2D.GraphicsPath path = new GraphicsPath();
- //添加箭头
- if (_bArrow)
- {
- Point headPoint = _points[_points.Count - 1];
- Point tailPoint = _points[_points.Count - 2];
- Point pos2 = new Point();
- Point pos3 = new Point();
- TwoPointPos twoPointPos = GetTwoPointPos(tailPoint, headPoint);
- switch (twoPointPos)
- {
- case TwoPointPos.Up:
- pos2.X = headPoint.X - (_lineWidth * 2);
- pos2.Y = headPoint.Y + (_lineWidth * 2);
- pos3.X = headPoint.X + (_lineWidth * 2);
- pos3.Y = pos2.Y;
- break;
- case TwoPointPos.Down:
- pos2.X = headPoint.X - (_lineWidth * 2);
- pos2.Y = headPoint.Y - (_lineWidth * 2);
- pos3.X = headPoint.X + (_lineWidth * 2);
- pos3.Y = pos2.Y;
- break;
- case TwoPointPos.Left:
- pos2.X = headPoint.X + (_lineWidth * 2);
- pos2.Y = headPoint.Y - (_lineWidth * 2);
- pos3.X = pos2.X;
- pos3.Y = headPoint.Y + (_lineWidth * 2);
- break;
- case TwoPointPos.Right:
- pos2.X = headPoint.X - (_lineWidth * 2);
- pos2.Y = headPoint.Y - (_lineWidth * 2);
- pos3.X = pos2.X;
- pos3.Y = headPoint.Y + (_lineWidth * 2);
- break;
- }
- Point[] arrowPoints = new Point[] { headPoint, pos2, pos3 };
- path.AddPolygon(arrowPoints);
- }
- path.AddRectangles(rects.ToArray());
- return path;
- }
- /// <summary>
- /// 设置控件的区域
- /// </summary>
- void SetControlRegion()
- {
- ResetControlGraphicsPath();
- if(_graphicsPath != null)
- this.Region = new Region(_graphicsPath);
- }
- /// <summary>
- /// 判断2个点的位置,第二个相对于第一个点的位置
- ///
- /// </summary>
- /// <param name="point1"></param>
- /// <param name="point2"></param>
- /// <returns></returns>
- public static TwoPointPos GetTwoPointPos(Point point1, Point point2)
- {
- if (point2.X > point1.X)
- {
- return TwoPointPos.Right;
- }
- else if (point2.X < point1.X)
- {
- return TwoPointPos.Left;
- }
- else
- {
- if (point2.Y > point1.Y)
- return TwoPointPos.Down;
- else
- return TwoPointPos.Up;
- }
- }
- /// <summary>
- /// 判断三个点的位置
- /// </summary>
- /// <param name="point1"></param>
- /// <param name="point2"></param>
- /// <param name="point3"></param>
- /// <returns></returns>
- ThreePointPos GetThreePointPos(Point point1, Point point2, Point point3)
- {
- TwoPointPos point2Pos = GetTwoPointPos(point1, point2);
- TwoPointPos point3Pos = GetTwoPointPos(point2, point3);
- if (point2Pos == TwoPointPos.Right)
- {
- if (point3Pos == TwoPointPos.Right)
- return ThreePointPos.Right;
- else if (point3Pos == TwoPointPos.Up)
- return ThreePointPos.RightUp;
- else if (point3Pos == TwoPointPos.Down)
- return ThreePointPos.RightDown;
- }
- else if (point2Pos == TwoPointPos.Left)
- {
- if (point3Pos == TwoPointPos.Left)
- return ThreePointPos.Left;
- else if (point3Pos == TwoPointPos.Up)
- return ThreePointPos.LeftUp;
- else if (point3Pos == TwoPointPos.Down)
- return ThreePointPos.LeftDown;
- }
- else if (point2Pos == TwoPointPos.Up)
- {
- if (point3Pos == TwoPointPos.Up)
- return ThreePointPos.Up;
- else if (point3Pos == TwoPointPos.Right)
- return ThreePointPos.UpRight;
- else if (point3Pos == TwoPointPos.Left)
- return ThreePointPos.UpLeft;
- }
- //Down
- if (point3Pos == TwoPointPos.Down)
- return ThreePointPos.Down;
- else if (point3Pos == TwoPointPos.Right)
- return ThreePointPos.DownRight;
- //Left
- return ThreePointPos.DownLeft;
- }
- #endregion
- #region 控件响应方法
- #endregion
- }
- /// <summary>
- /// 两个点相对位置类型
- /// </summary>
- public enum TwoPointPos
- {
- Left,
- Up,
- Right,
- Down,
- }
- /// <summary>
- /// 三个点相对位置类型
- /// </summary>
- public enum ThreePointPos
- {
- LeftUp,
- RightUp,
- RightDown,
- LeftDown,
- UpRight,
- UpLeft,
- DownLeft,
- DownRight,
- Left,
- Right,
- Up,
- Down,
- }
- }
|