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,
}
}