using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WinCustControls
{
public partial class UCPipe : UserControl
{
public UCPipe()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint, true);//忽略窗口消息,减少闪烁
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//绘制到缓冲区,减少闪烁
SetStyle(ControlStyles.UserPaint, true);//控件由其自身而不是操作系统绘制
SetStyle(ControlStyles.ResizeRedraw, true);//控件调整其大小时重绘
SetStyle(ControlStyles.SupportsTransparentBackColor, true);//支持透明背景
SizeChanged += UCPipe_SizeChanged;
this.Size = new Size(200, 30);
timer = new System.Timers.Timer();
timer.Interval = 100;
timer.AutoReset = true;
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
intLineLeft += 2;
if (intLineLeft > 12)
{
intLineLeft = 0;
}
Invalidate();
}
System.Timers.Timer timer = null;
int intLineLeft = 0;//线的左边距离
int intPenWidth = 0;//圆弧的半径
private void UCPipe_SizeChanged(object sender, EventArgs e)
{
intPenWidth = pipeStyle.ToString().Substring(0, 1) == "H" ? Height : Width;
}
private PipeStyle pipeStyle = PipeStyle.Horizontal_None_None;
[DefaultValue(typeof(PipeStyle), "Horizontal_None_None"), Description("管道样式")]
public PipeStyle PipeStyle
{
get { return pipeStyle; }
set
{
string oldStr = pipeStyle.ToString().Substring(0, 1);
string newStr = value.ToString().Substring(0, 1);
pipeStyle = value;
if (oldStr != newStr)
{
Size = new Size(Size.Height, Size.Width);
}
Invalidate();
}
}
private bool isFlow = false;
[DefaultValue(typeof(bool), "False"), Description("是否流动")]
public bool IsFlow
{
get { return isFlow; }
set
{
isFlow = value;
if (isFlow)
{
timer.Start();
}
else
{
timer.Stop();
}
Invalidate();
}
}
private int flowWidth = 4;
[DefaultValue(typeof(int), "4"), Description("流动线的粗细")]
public int FlowWidth
{
get { return flowWidth; }
set
{
flowWidth = value;
if (flowWidth <= 0)
return;
Invalidate();
}
}
private int flowLength = 8;
[DefaultValue(typeof(int), "4"), Description("流动线的长度")]
public int FlowLength
{
get { return flowLength; }
set
{
flowLength = value;
Invalidate();
}
}
private int flowSpace = 6;
[DefaultValue(typeof(int), "6"), Description("流动线的间隔")]
public int FlowSpace
{
get { return flowSpace; }
set
{
flowSpace = value;
Invalidate();
}
}
private Color pipeColor = Color.LightBlue;
[DefaultValue(typeof(Color), "LightBlue"), Description("管道的颜色")]
public Color PipeColor
{
get { return pipeColor; }
set
{
pipeColor = value;
Invalidate();
}
}
private Color flowColor = Color.White;
[DefaultValue(typeof(Color), "White"), Description("流动线的颜色")]
public Color FlowColor
{
get { return flowColor; }
set
{
flowColor = value;
Invalidate();
}
}
private FlowDirection flowDirection = FlowDirection.Forward;
[DefaultValue(typeof(FlowDirection), "Forward"), Description("流动的方向")]
public FlowDirection FlowDirection
{
get { return flowDirection; }
set
{
flowDirection = value;
Invalidate();
}
}
private int flowSpeed = 100;
[DefaultValue(typeof(int), "100"), Description("流动速度")]
public int FlowSpeed
{
get { return flowSpeed; }
set
{
if (value <= 0)
return;
flowSpeed = value;
timer.Interval = flowSpeed;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
//管道轮廓路径
GraphicsPath path = new GraphicsPath();
//流动线外围的路径
GraphicsPath linePath = new GraphicsPath();
switch (pipeStyle)
{
case PipeStyle.Horizontal_None_None://水平
path.AddLines(new PointF[] {
new PointF(0,0),
new PointF(ClientRectangle.Right,0),
new PointF(ClientRectangle.Right,Height),
new PointF(0,Height)
});
path.CloseAllFigures();//闭合
//添加中间流动线路径
linePath.AddLine(0, Height / 2, Width, Height / 2);
break;
case PipeStyle.Horizontal_Up_None://水平左上弯
path.AddLines(new PointF[]
{
new PointF(0, 0),
new PointF(this.ClientRectangle.Right, 0),
new PointF(this.ClientRectangle.Right, this.Height),
new PointF(0+intPenWidth, this.Height)//左下角点 下边直线弯道前的点
});
//添加上弯弧线 所在圆的矩形左上角y:intPenWidth * -1
path.AddArc(new Rectangle(0, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.CloseAllFigures();//闭合
//添加中间流动线 左边圆弧+右边直线
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 181, -91);
//右边直线
linePath.AddLine(intPenWidth, this.Height / 2, this.Width, this.Height / 2);
break;
case PipeStyle.Horizontal_Down_None://水平左下弯
path.AddLines(new PointF[]
{
new PointF(intPenWidth, 0),//上边横线的起点
new PointF(this.ClientRectangle.Right, 0),//右上角点
new PointF(this.ClientRectangle.Right, this.Height),//右下角点
new PointF(0, this.Height)//左下角点
});
//左上角圆弧 向上旋转90度
path.AddArc(new Rectangle(0, 0, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();//闭合
//添加流动线向上旋转弧
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, this.Height / 2, intPenWidth, intPenWidth), 179, 91);
//流动线 向右直线
linePath.AddLine(intPenWidth + 1, this.Height / 2, this.Width, this.Height / 2);
break;
case PipeStyle.Horizontal_None_Up://水平右上弯
path.AddLines(new PointF[]
{
//右下角直线起点(右边就是向下旋转弧)
new PointF(this.ClientRectangle.Right-intPenWidth, this.Height),
//左下角点
new PointF(0, this.Height),
//左上角点
new PointF(0, 0),
//右上角点
new PointF(this.ClientRectangle.Right, 0)
});
//添加右下角弧线
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 0, 90);
path.CloseAllFigures();
//添加中间流动线
linePath.AddLine(0, this.Height / 2, this.Width - intPenWidth, this.Height / 2);
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 91, -91);
break;
case PipeStyle.Horizontal_None_Down://水平右下弯
path.AddLines(new PointF[]
{
new PointF(this.ClientRectangle.Right, this.Height),//右下角点
new PointF(0, this.Height),//右下角点
new PointF(0, 0),//左上角点
new PointF(this.ClientRectangle.Right-intPenWidth, 0)//右上角点(右边是向下圆弧)
});
//添加右上角弧线
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, -1, intPenWidth * 2, intPenWidth * 2), 270, 90);
path.CloseAllFigures();
//添加流动线+弧线
linePath.AddLine(0, this.Height / 2, this.Width - intPenWidth - 1, this.Height / 2);
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, intPenWidth / 2, intPenWidth, intPenWidth), 269, 91);
break;
case PipeStyle.Horizontal_Down_Up://水平左下右上
//添加上边直线(去掉弧线部分)
path.AddLine(new Point(intPenWidth, 0), new Point(this.Width, 0));
//添加右下角弧线
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 0, 90);
//添加下线直线
path.AddLine(new Point(this.Width - intPenWidth, this.Height), new Point(0, this.Height));
//添加左上角弧线
path.AddArc(new Rectangle(0, 0, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();
//添加流动线圆弧 左上
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, this.Height / 2, intPenWidth, intPenWidth), 179, 91);
//添加流动线圆弧 右下
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 91, -91);
break;
case PipeStyle.Horizontal_Up_Down://左上右下
//添加上直线
path.AddLine(new Point(0, 0), new Point(this.Width - intPenWidth, 0));
//右上圆弧
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, -1, intPenWidth * 2, intPenWidth * 2), 270, 90);
//添加下直线
path.AddLine(new Point(this.Width, this.Height), new Point(intPenWidth, this.Height));
//添加左下圆弧
path.AddArc(new Rectangle(0, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.CloseAllFigures();
//流动线 添加圆弧 左上
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 181, -91);
//流动线 中间直接
linePath.AddLine(intPenWidth, this.Height / 2, this.Width - intPenWidth - 1, this.Height / 2);
//流动线 右下圆弧
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, intPenWidth / 2, intPenWidth, intPenWidth), 269, 91);
break;
case PipeStyle.Horizontal_Up_Up://左上右上
//上边直线
path.AddLine(new Point(0, 0), new Point(this.Width, 0));
//右下圆弧
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 0, 90);
//下边直线
path.AddLine(new Point(this.Width - intPenWidth, this.Height), new Point(intPenWidth, this.Height));
//左上圆弧
path.AddArc(new Rectangle(0, intPenWidth * -1, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.CloseAllFigures();
//添加流动线右下圆弧
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 181, -91);
//添加流动线左下圆弧
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, -1 * intPenWidth / 2 - 1, intPenWidth, intPenWidth), 91, -91);
//添加左下圆弧
break;
case PipeStyle.Horizontal_Down_Down://水平左下右下
//上边直线
path.AddLine(new Point(intPenWidth, 0), new Point(this.Width - intPenWidth, 0));
//右上角圆弧
path.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth * 2, -1, intPenWidth * 2, intPenWidth * 2), 270, 90);
//下边线
path.AddLine(new Point(this.Width, this.Height), new Point(0, this.Height));
//左上角圆弧
path.AddArc(new Rectangle(0, -1, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();
//添加流动线 左上角圆弧
linePath.AddArc(new Rectangle(intPenWidth / 2 + 1, this.Height / 2, intPenWidth, intPenWidth), 179, 91);
//中间直线
linePath.AddLine(intPenWidth + 1, this.Height / 2, this.Width - intPenWidth - 1, this.Height / 2);
//右上角圆弧
linePath.AddArc(new Rectangle(this.ClientRectangle.Right - intPenWidth - intPenWidth / 2 - 1, intPenWidth / 2, intPenWidth, intPenWidth), 269, 91);
break;
case PipeStyle.Vertical_None_None:
path.AddLines(new PointF[]
{
new PointF(0, 0),
new PointF(this.ClientRectangle.Right, 0),
new PointF(this.ClientRectangle.Right, this.Height),
new PointF(0, this.Height)
});
path.CloseAllFigures();
linePath.AddLine(this.Width / 2, 0, this.Width / 2, this.Height);
break;
case PipeStyle.Vertical_Left_None:
path.AddLines(new PointF[]
{
new PointF(this.ClientRectangle.Right, intPenWidth),
new PointF(this.ClientRectangle.Right, this.Height),
new PointF(0, this.Height),
new PointF(0, 0)
});
path.AddArc(new Rectangle(-1 * intPenWidth, 0, intPenWidth * 2, intPenWidth * 2), 270, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 269, 91);
linePath.AddLine(intPenWidth / 2, intPenWidth, intPenWidth / 2, this.Height);
break;
case PipeStyle.Vertical_Right_None:
path.AddLines(new PointF[]
{
new PointF(this.ClientRectangle.Right, 0),
new PointF(this.ClientRectangle.Right, this.Height),
new PointF(0, this.Height),
new PointF(0, intPenWidth)
});
path.AddArc(new Rectangle(-1, 0, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(intPenWidth / 2, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 271, -91);
linePath.AddLine(intPenWidth / 2, intPenWidth + 1, intPenWidth / 2, this.Height);
break;
case PipeStyle.Vertical_None_Left:
path.AddLines(new PointF[]
{
new PointF(0, this.Height),
new PointF(0, 0),
new PointF(this.ClientRectangle.Right, 0),
new PointF(this.ClientRectangle.Right, this.Height-intPenWidth),
});
path.AddArc(new Rectangle(-1 * intPenWidth, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 0, 90);
path.CloseAllFigures();
linePath.AddLine(this.Width / 2, 0, this.Width / 2, this.Height - intPenWidth);
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), -1, 91);
break;
case PipeStyle.Vertical_None_Right:
path.AddLines(new PointF[]
{
new PointF(0, this.Height-intPenWidth),
new PointF(0, 0),
new PointF(this.ClientRectangle.Right, 0),
new PointF(this.ClientRectangle.Right, this.Height),
});
path.AddArc(new Rectangle(-1, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.CloseAllFigures();
linePath.AddLine(this.Width / 2, 0, this.Width / 2, this.Height - intPenWidth - 1);
linePath.AddArc(new Rectangle(intPenWidth / 2, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), 181, -91);
break;
case PipeStyle.Vertical_Left_Right:
path.AddLine(this.Width, intPenWidth, this.Width, this.Height);
path.AddArc(new Rectangle(-1, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.AddLine(0, this.Height - intPenWidth, 0, 0);
path.AddArc(new Rectangle(-1 * intPenWidth, 0, intPenWidth * 2, intPenWidth * 2), 270, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 269, 91);
linePath.AddArc(new Rectangle(intPenWidth / 2, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), 181, -91);
break;
case PipeStyle.Vertical_Right_Left:
path.AddLine(this.Width, 0, this.Width, this.Height - intPenWidth);
path.AddArc(new Rectangle(-1 * intPenWidth, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 0, 90);
path.AddLine(0, this.Height, 0, intPenWidth);
path.AddArc(new Rectangle(-1, 0, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(intPenWidth / 2, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 271, -91);
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), -1, 91);
break;
case PipeStyle.Vertical_Left_Left:
path.AddLine(this.Width, intPenWidth, this.Width, this.Height - intPenWidth);
path.AddArc(new Rectangle(-1 * intPenWidth, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 0, 90);
path.AddLine(0, this.Height, 0, 0);
path.AddArc(new Rectangle(-1 * intPenWidth, 0, intPenWidth * 2, intPenWidth * 2), 270, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 269, 91);
linePath.AddArc(new Rectangle(-1 * intPenWidth / 2 - 1, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), -1, 91);
break;
case PipeStyle.Vertical_Right_Right:
path.AddLine(this.Width, 0, this.Width, this.Height);
path.AddArc(new Rectangle(-1, this.Height - intPenWidth * 2, intPenWidth * 2, intPenWidth * 2), 90, 90);
path.AddLine(0, this.Height - intPenWidth, 0, intPenWidth);
path.AddArc(new Rectangle(-1, 0, intPenWidth * 2, intPenWidth * 2), 180, 90);
path.CloseAllFigures();
linePath.AddArc(new Rectangle(intPenWidth / 2, intPenWidth / 2 + 1, intPenWidth, intPenWidth), 271, -91);
linePath.AddArc(new Rectangle(intPenWidth / 2, this.Height - intPenWidth - intPenWidth / 2 - 1, intPenWidth, intPenWidth), 180, -91);
break;
}
//填充管道颜色
g.FillPath(new SolidBrush(PipeColor), path);
//渐变色
int intCount = intPenWidth / 2 / 4;
int intSplit = (255 - 100) / intCount;
for (int i = 0; i < intCount; i++)
{
int _penWidth = intPenWidth / 2 - 4 * i;
if (_penWidth <= 0)
_penWidth = 1;
//画流动线外围的渐变色(浅白部分)
g.DrawPath(new Pen(new SolidBrush(Color.FromArgb(40, Color.White.R, Color.White.G, Color.White.B)), _penWidth), linePath);
if (_penWidth == 1)
break;
}
//液体的流动
if (flowDirection != FlowDirection.None)
{
Pen p = new Pen(new SolidBrush(flowColor), flowWidth);
//虚线的样式
p.DashPattern = new float[] { flowLength, flowSpace };
p.DashOffset = intLineLeft * (FlowDirection == FlowDirection.Forward ? -1 : 1);
g.DrawPath(p, linePath);
}
}
}
///
/// 管道样式
///
public enum PipeStyle
{
///
/// 直线
///
Horizontal_None_None,
///
/// 左上
///
Horizontal_Up_None,
///
/// 左下
///
Horizontal_Down_None,
///
/// 右上
///
Horizontal_None_Up,
///
/// 右下
///
Horizontal_None_Down,
///
/// 左下右上
///
Horizontal_Down_Up,
///
/// 左上右下
///
Horizontal_Up_Down,
///
/// 左上,右上
///
Horizontal_Up_Up,
///
/// 左下右下
///
Horizontal_Down_Down,
///
/// 竖线
///
Vertical_None_None,
///
/// 上左
///
Vertical_Left_None,
///
/// 上右
///
Vertical_Right_None,
///
/// 下左
///
Vertical_None_Left,
///
/// 下右
///
Vertical_None_Right,
///
/// 上左下右
///
Vertical_Left_Right,
///
/// 上右下左
///
Vertical_Right_Left,
///
/// 上左下左
///
Vertical_Left_Left,
///
/// 上右下右
///
Vertical_Right_Right,
}
///
/// 流动方向
///
public enum FlowDirection
{
None,
///
/// 向后
///
Forward,
///
/// 向前
///
Backward
}
}