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 字段 /// /// 线宽 /// int _lineWidth = 2; /// /// 线半宽 /// int _lineHalfWidth = 1; /// /// 图形路径 /// GraphicsPath _graphicsPath; /// /// 折线点 /// List _points; /// /// 线颜色 /// Color _lineColor; /// /// 被选中时的线颜色 /// Color _selectedLineColor; /// /// 是否有箭头 /// bool _bArrow = true; /// /// 绑定的线对象 /// FlowLine _flowLine; /// /// 是否被选中 /// bool _bSelected; #endregion #region 属性 /// /// 折线组成的点的列表 /// public List PointList { get { return _points; } set { _points = value; SetControlRegion(); } } /// /// 线颜色 /// public Color LineColor { get { return _lineColor; } set { _lineColor = value; if (!_bSelected) BackColor = _lineColor; } } /// /// 被选中时的线颜色 /// public Color SelectedLineColor { get { return _selectedLineColor; } set { _selectedLineColor = value; if (_bSelected) BackColor = _lineColor; } } /// /// 是否被选中 /// public bool BeSelected { get { return _bSelected; } set { if (_bSelected != value) { _bSelected = value; if (_bSelected) BackColor = _selectedLineColor; else BackColor = _lineColor; } } } /// /// 线宽 /// public int LineWidth { get { return _lineWidth; } set { if(value < 2) _lineWidth = 2; else _lineWidth = value; _lineHalfWidth = (_lineWidth + 1) / 2; SetControlRegion(); } } /// /// 绑定的线对象 /// public FlowLine FlowLine { get { return _flowLine; } set { _flowLine = value; } } #endregion #region 公开方法 /// /// 构造方法 /// public FlowBrokenLineControl() { InitializeComponent(); this.BackColor = _lineColor; this.BorderStyle = System.Windows.Forms.BorderStyle.None; this.ResumeLayout(false); } /// /// 构造方法 /// /// 绑定的线 public FlowBrokenLineControl(FlowLine line) { InitializeComponent(); _flowLine = line; this.BackColor = _lineColor; this.BorderStyle = System.Windows.Forms.BorderStyle.None; this.ResumeLayout(false); } #endregion #region 私有方法 /// /// 重新设置控件的GraphicsPath /// void ResetControlGraphicsPath() { _graphicsPath = GetGraphicsPath(); } /// /// (废弃的)获取GraphicsPath /// /// 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; } /// /// 获取GraphicsPath /// /// 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; } /// /// 设置控件的区域 /// void SetControlRegion() { ResetControlGraphicsPath(); if(_graphicsPath != null) this.Region = new Region(_graphicsPath); } /// /// 判断2个点的位置,第二个相对于第一个点的位置 /// /// /// /// /// 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; } } /// /// 判断三个点的位置 /// /// /// /// /// 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 } /// /// 两个点相对位置类型 /// public enum TwoPointPos { Left, Up, Right, Down, } /// /// 三个点相对位置类型 /// public enum ThreePointPos { LeftUp, RightUp, RightDown, LeftDown, UpRight, UpLeft, DownLeft, DownRight, Left, Right, Up, Down, } }