添加项目文件。
This commit is contained in:
417
CowainHmi/ucArrowLine.cs
Normal file
417
CowainHmi/ucArrowLine.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
using PCHMI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CowainHmi
|
||||
{
|
||||
public enum LineDirection
|
||||
{
|
||||
左上右下,
|
||||
左下右上,
|
||||
水平,
|
||||
垂直
|
||||
}
|
||||
|
||||
public enum ArrowType
|
||||
{
|
||||
无箭头,
|
||||
结束箭头,
|
||||
开始箭头,
|
||||
双箭头
|
||||
}
|
||||
|
||||
public partial class ucArrowLine : Control
|
||||
{
|
||||
|
||||
// 私有字段
|
||||
private int _lineWidth = 2;
|
||||
private int _arrowWidth = 10;
|
||||
private int _arrowHeight = 5;
|
||||
private LineDirection _angle = LineDirection.水平;
|
||||
private ArrowType _arrowType = ArrowType.无箭头;
|
||||
private Color _lineColor = Color.Teal;
|
||||
private PointF _startPoint = new PointF(50, 50);
|
||||
private PointF _endPoint = new PointF(200, 50);
|
||||
|
||||
// 公共属性
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int LineWidth
|
||||
{
|
||||
get { return _lineWidth; }
|
||||
set
|
||||
{
|
||||
_lineWidth = value;
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
// 公共属性
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Color LineColor
|
||||
{
|
||||
get { return _lineColor; }
|
||||
set
|
||||
{
|
||||
_lineColor = value;
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int ArrowWidth
|
||||
{
|
||||
get { return _arrowWidth; }
|
||||
set
|
||||
{
|
||||
_arrowWidth = value;
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int ArrowHeight
|
||||
{
|
||||
get { return _arrowHeight; }
|
||||
set
|
||||
{
|
||||
_arrowHeight = value;
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public LineDirection Angle
|
||||
{
|
||||
get { return _angle; }
|
||||
set
|
||||
{
|
||||
_angle = value;
|
||||
CalculatePoint(); // 重新计算终点位置
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public ArrowType ArrowType
|
||||
{
|
||||
get { return _arrowType; }
|
||||
set
|
||||
{
|
||||
_arrowType = value;
|
||||
CalculatePoint(); // 重新计算终点位置
|
||||
Draw(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
public ucArrowLine()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetStyle(ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, value: true);
|
||||
SetStyle(ControlStyles.Selectable, value: false);
|
||||
BackColor = Color.Transparent;
|
||||
this.Resize += new EventHandler(this.ArrowLineControl_Resize);
|
||||
this.Size = new Size(300, 100); // 设置控件大小
|
||||
}
|
||||
|
||||
|
||||
// 控件大小改变时调整
|
||||
private void ArrowLineControl_Resize(object sender, EventArgs e)
|
||||
{
|
||||
CalculatePoint();
|
||||
Draw();
|
||||
}
|
||||
|
||||
// 根据方向更新起点和终点
|
||||
private void CalculatePoint()
|
||||
{
|
||||
switch (Angle)
|
||||
{
|
||||
case LineDirection.水平:
|
||||
_startPoint = new PointF(0, this.Height / 2);
|
||||
_endPoint = new PointF(this.Width - 4, this.Height / 2);
|
||||
break;
|
||||
case LineDirection.垂直:
|
||||
_startPoint = new PointF(this.Width / 2, 0);
|
||||
_endPoint = new PointF(this.Width / 2, this.Height);
|
||||
break;
|
||||
case LineDirection.左上右下:
|
||||
_startPoint = new PointF(0, 0);
|
||||
_endPoint = new PointF(this.Width, this.Height);
|
||||
break;
|
||||
case LineDirection.左下右上:
|
||||
_startPoint = new PointF(0, this.Height);
|
||||
_endPoint = new PointF(this.Width, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private Bitmap bmp;
|
||||
// 重写OnPaint方法
|
||||
private void Draw()
|
||||
{
|
||||
bmp = new Bitmap(base.Width, base.Height);
|
||||
Graphics graphics = Graphics.FromImage(bmp);
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
// 绘制线段
|
||||
Pen linePen = new Pen(LineColor, _lineWidth);
|
||||
graphics.DrawLine(linePen, _startPoint, _endPoint);
|
||||
switch (_arrowType)
|
||||
{
|
||||
case ArrowType.结束箭头:
|
||||
graphics.FillPolygon(linePen.Brush, DrawArrow(graphics, _startPoint, _endPoint, ArrowWidth, ArrowHeight));
|
||||
break;
|
||||
case ArrowType.开始箭头:
|
||||
graphics.FillPolygon(linePen.Brush, DrawArrow(graphics, _endPoint, _startPoint, ArrowWidth, ArrowHeight));
|
||||
break;
|
||||
case ArrowType.双箭头:
|
||||
graphics.FillPolygon(linePen.Brush, DrawArrow(graphics, _startPoint, _endPoint, ArrowWidth, ArrowHeight));
|
||||
graphics.FillPolygon(linePen.Brush, DrawArrow(graphics, _endPoint, _startPoint, ArrowWidth, ArrowHeight));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BackgroundImage = bmp;
|
||||
//设置显示区域,区域外透明
|
||||
RegionControl(_startPoint, _endPoint);
|
||||
linePen.Dispose();
|
||||
graphics.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取箭头的三个点
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private PointF[] DrawArrow(Graphics g, PointF start, PointF end, int arrowWidth, int arrowHeigth)
|
||||
{
|
||||
|
||||
double angle = Math.Atan2(end.Y - start.Y, end.X - start.X);
|
||||
double left_x = end.X - arrowWidth * Math.Cos(angle);
|
||||
double left_y = end.Y - arrowWidth * Math.Sin(angle);
|
||||
PointF p1 = end;
|
||||
PointF p2 = new PointF
|
||||
{
|
||||
X = (float)(left_x + (arrowHeigth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y + (arrowHeigth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p3 = new PointF
|
||||
{
|
||||
X = (float)(left_x - (arrowHeigth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y - (arrowHeigth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
return new PointF[] { p1, p2, p3 };
|
||||
}
|
||||
private void RegionControl(PointF start, PointF end)
|
||||
{
|
||||
PointF[] points = new PointF[] { };
|
||||
//设置区域,区域外透明
|
||||
|
||||
switch (_arrowType)
|
||||
{
|
||||
case ArrowType.无箭头:
|
||||
points = GetNoArrowRegion(_startPoint, _endPoint);
|
||||
break;
|
||||
case ArrowType.结束箭头:
|
||||
points = GetEndArrowRegion(_startPoint, _endPoint);
|
||||
break;
|
||||
case ArrowType.开始箭头:
|
||||
points = GetEndArrowRegion(_endPoint, _startPoint);
|
||||
break;
|
||||
case ArrowType.双箭头:
|
||||
points = GetBothArrowRegion(_startPoint, _endPoint);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GraphicsPath graphicsPath = new GraphicsPath();
|
||||
graphicsPath.AddPolygon(points);
|
||||
Region region = new Region(graphicsPath);
|
||||
this.Region = region;
|
||||
}
|
||||
|
||||
private PointF[] GetNoArrowRegion(PointF start, PointF end)
|
||||
{
|
||||
double angle = Math.Atan2(end.Y - start.Y, end.X - start.X);
|
||||
PointF p1 = new PointF
|
||||
{
|
||||
X = (float)(start.X - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(start.Y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p2 = new PointF
|
||||
{
|
||||
X = (float)(start.X + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(start.Y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p3 = new PointF
|
||||
{
|
||||
X = (float)(end.X + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(end.Y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p4 = new PointF
|
||||
{
|
||||
X = (float)(end.X - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(end.Y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
return new PointF[] { p1, p2, p3, p4 };
|
||||
}
|
||||
|
||||
private PointF[] GetEndArrowRegion(PointF start, PointF end)
|
||||
{
|
||||
double length = Math.Sqrt((end.Y - start.Y) * (end.Y - start.Y) + (end.X - start.X) * (end.X - start.X));
|
||||
double angle = Math.Atan2(end.Y - start.Y, end.X - start.X);
|
||||
double left_x = end.X - ArrowWidth * Math.Cos(angle);
|
||||
double left_y = end.Y - ArrowWidth * Math.Sin(angle);
|
||||
PointF p1 = new PointF
|
||||
{
|
||||
X = (float)(start.X - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(start.Y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p2 = new PointF
|
||||
{
|
||||
X = (float)(start.X + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(start.Y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p3 = new PointF
|
||||
{
|
||||
X = (float)(left_x + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p4 = new PointF
|
||||
{
|
||||
X = (float)(left_x + (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y + (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p5 = end;
|
||||
PointF p6 = new PointF
|
||||
{
|
||||
X = (float)(left_x - (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y - (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p7 = new PointF
|
||||
{
|
||||
X = (float)(left_x - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
return new PointF[] { p1, p2, p3, p4, p5, p6, p7 };
|
||||
}
|
||||
|
||||
private PointF[] GetBothArrowRegion(PointF start, PointF end)
|
||||
{
|
||||
double length = Math.Sqrt((end.Y - start.Y) * (end.Y - start.Y) + (end.X - start.X) * (end.X - start.X));
|
||||
double angle = Math.Atan2(end.Y - start.Y, end.X - start.X);
|
||||
double left_end_x = end.X - ArrowWidth * Math.Cos(angle);
|
||||
double left_end_y = end.Y - ArrowWidth * Math.Sin(angle);
|
||||
double left_start_x = start.X + ArrowWidth * Math.Cos(angle);
|
||||
double left_start_y = start.Y + ArrowWidth * Math.Sin(angle);
|
||||
PointF p1 = new PointF
|
||||
{
|
||||
X = (float)(left_start_x - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_start_y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p2 = new PointF
|
||||
{
|
||||
X = (float)(left_start_x - (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_start_y - (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p3 = start;
|
||||
PointF p4 = new PointF
|
||||
{
|
||||
X = (float)(left_start_x + (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_start_y + (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p5 = new PointF
|
||||
{
|
||||
X = (float)(left_start_x + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_start_y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p6 = new PointF
|
||||
{
|
||||
X = (float)(left_end_x + (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_end_y + (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p7 = new PointF
|
||||
{
|
||||
X = (float)(left_end_x + (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_end_y + (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p8 = end;
|
||||
PointF p9 = new PointF
|
||||
{
|
||||
X = (float)(left_end_x - (ArrowHeight / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_end_y - (ArrowHeight / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
PointF p10 = new PointF
|
||||
{
|
||||
X = (float)(left_end_x - (_lineWidth / 2) * Math.Cos(angle + Math.PI / 2)),
|
||||
Y = (float)(left_end_y - (_lineWidth / 2) * Math.Sin(angle + Math.PI / 2))
|
||||
};
|
||||
return new PointF[] { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 };
|
||||
}
|
||||
private void RegionControl()
|
||||
{
|
||||
//设置区域,区域外透明
|
||||
Point[] points = new Point[4]
|
||||
{
|
||||
new Point(0, this.Height / 2 + _lineWidth/2),
|
||||
new Point(0, this.Height / 2 - _lineWidth/2),
|
||||
new Point(this.Width, this.Height / 2 - _lineWidth/2),
|
||||
new Point(this.Width, this.Height / 2 + _lineWidth/2)
|
||||
};
|
||||
switch (Angle)
|
||||
{
|
||||
case LineDirection.水平:
|
||||
points = new Point[4]
|
||||
{
|
||||
new Point(0, this.Height / 2 + _lineWidth/2),
|
||||
new Point(0, this.Height / 2 - _lineWidth/2),
|
||||
new Point(this.Width, this.Height / 2 - _lineWidth/2),
|
||||
new Point(this.Width, this.Height / 2 + _lineWidth/2)
|
||||
};
|
||||
break;
|
||||
case LineDirection.垂直:
|
||||
points = new Point[4]
|
||||
{
|
||||
new Point(this.Width/2 - _lineWidth/2, 0),
|
||||
new Point(this.Width/2 + _lineWidth/2, 0),
|
||||
new Point(this.Width/2 + _lineWidth/2, this.Height),
|
||||
new Point(this.Width/2 - _lineWidth/2, this.Height)
|
||||
};
|
||||
break;
|
||||
case LineDirection.左上右下:
|
||||
points = new Point[4]
|
||||
{
|
||||
new Point(0, base.Height / 2 + _lineWidth/2),
|
||||
new Point(0, base.Height / 2 - _lineWidth/2),
|
||||
new Point(base.Width, base.Height / 2 - _lineWidth/2),
|
||||
new Point(base.Width, base.Height / 2 + _lineWidth/2)
|
||||
};
|
||||
break;
|
||||
case LineDirection.左下右上:
|
||||
points = new Point[4]
|
||||
{
|
||||
new Point(0, base.Height / 2 + _lineWidth/2),
|
||||
new Point(0, base.Height / 2 - _lineWidth/2),
|
||||
new Point(base.Width, base.Height / 2 - _lineWidth/2),
|
||||
new Point(base.Width, base.Height / 2 + _lineWidth/2)
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
GraphicsPath graphicsPath = new GraphicsPath();
|
||||
graphicsPath.AddPolygon(points);
|
||||
Region region = new Region(graphicsPath);
|
||||
this.Region = region;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user