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