using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Windows.Forms.VisualStyles;
namespace ControlLibrary
{
/// <summary>
/// 管道左、右的转向类型
/// </summary>
public enum PipeTurnDirection
{
Up = 1,
Down,
Left,
Right,
None
}
/// <summary>
/// 管道的样式,水平还是数值
/// </summary>
public enum DirectionStyle
{
Horizontal = 1,
Vertical
}
public partial class UserControl1: UserControl
{
public UserControl1()
{
InitializeComponent();
//对本身进行设置
//设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); //减少闪烁
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); //双缓冲,也是减少闪烁
this.SetStyle(ControlStyles.ResizeRedraw, true); //调整大小
this.SetStyle(ControlStyles.Selectable, true); //接收焦点
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); //模拟透明度
this.SetStyle(ControlStyles.UserPaint, true); //控件描绘控件本身
//自动移动
mytimer = new Timer();
mytimer.Tick += Mytimer_Tick;
mytimer.Enabled = true;
}
//移动
private void Mytimer_Tick(object sender, EventArgs e)
{
startOffset -= moveSpeed; //减才是向右移动
if (startOffset > (this.gapLength + this.pipeLength))
{
startOffset = 0;
}
this.Invalidate(); //没有这个不会动,有这个才会重写绘制
}
private Graphics g; //画布
private Pen p; //画笔
private Timer mytimer;
private float startOffset = 0.0f;
#region Fileds
private int pipeWidth = 5;
[Browsable(true), Category("自定义属性"), Description("流动条宽度")]
public int PipeWidth
{
get { return pipeWidth; }
set
{
this.pipeWidth = value;
base.Invalidate(); //this和base是一样的,这个是Windows.Forms里面的方法,调用父类和子类是一样的
}
}
private Color colorCenter = Color.DodgerBlue;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的流动颜色")]
public Color ColorCenter
{
get
{
return this.colorCenter;
}
set
{
this.colorCenter = value;
base.Invalidate();
}
}
private Color borderColor = Color.DimGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道边线颜色")]
public Color BorderColor
{
get
{
return this.borderColor;
}
set
{
this.borderColor = value;
p = new Pen(value, 1.0f); //画边框笔的颜色
base.Invalidate();
}
}
private Color edgeColor = Color.DimGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道边缘颜色")]
public Color EdgeColor
{
get
{
return this.edgeColor;
}
set
{
this.edgeColor = value;
base.Invalidate();
}
}
private Color centerColor = Color.LightGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的中心颜色")]
public Color LineCenterColor
{
get
{
return this.centerColor;
}
set
{
this.centerColor = value;
base.Invalidate();
}
}
private PipeTurnDirection pipeTurnLeft = PipeTurnDirection.None;
[Browsable(true), Category("自定义属性"), Description("左管道的转向类型")]
public PipeTurnDirection PipeTurnLeft
{
get
{
return this.pipeTurnLeft;
}
set
{
this.pipeTurnLeft = value;
base.Invalidate();
}
}
private PipeTurnDirection pipeTurnRight = PipeTurnDirection.None;
[Browsable(true), Category("自定义属性"), Description("右管道的转向类型")]
public PipeTurnDirection PipeTurnRight
{
get
{
return this.pipeTurnRight;
}
set
{
this.pipeTurnRight = value;
base.Invalidate();
}
}
private DirectionStyle pipeLineStyle = DirectionStyle.Horizontal;
[Browsable(true), Category("自定义属性"), Description("设置管道是横向的还是纵向的")]
public DirectionStyle PipeLineStyle
{
get
{
return this.pipeLineStyle;
}
set
{
this.pipeLineStyle = value;
base.Invalidate();
}
}
private bool isActive = false;
[Browsable(true), Category("自定义属性"), DefaultValue(false), Description("获取或设置管道线是否激活液体显示")]
public bool IsActive
{
get
{
return this.isActive;
}
set
{
this.isActive = value;
this.mytimer.Enabled = value; //滚动条激活,靠这个动的
this.mytimer.Start();
base.Invalidate();
}
}
private float moveSpeed = 0.3f;
[Browsable(true), Category("自定义属性"), Description("管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
public float MoveSpeed
{
get
{
return this.moveSpeed;
}
set
{
this.moveSpeed = value;
base.Invalidate();
}
}
private int pipeLength = 5;
[Browsable(true), Category("自定义属性"), Description("流动条长度")]
public int PipeLength
{
get
{
return this.pipeLength;
}
set
{
this.pipeLength = value;
base.Invalidate();
}
}
private int gapLength = 5;
[Browsable(true), Category("自定义属性"), Description("间隙长度")]
public int GapLength
{
get
{
return this.gapLength;
}
set
{
this.gapLength = value;
base.Invalidate();
}
}
#endregion
//重写onPaint
protected override void OnPaint(PaintEventArgs e)
{
g = e.Graphics; //重事件中获取数据
//设置显示质量
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //设置文本质量
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //平滑-抗锯齿
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //这个也是抗锯齿
p = new Pen(this.BorderColor, 1.0f); //笔的颜色和笔头大小
//渐变颜色数组
ColorBlend colorBlend = new ColorBlend();
colorBlend.Positions = new float[]
{
0.0f, 0.5f, 1.0f
};
colorBlend.Colors = new Color[]
{
this.BorderColor, this.centerColor, this.borderColor
};
//水平管道
if (this.pipeLineStyle == DirectionStyle.Horizontal)
{
//水平方向的竖直刷
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height), edgeColor, borderColor);
linearGradientBrush.InterpolationColors = colorBlend; //这个是渐变的颜色
//左边弯曲
switch (this.pipeTurnLeft)
{
case PipeTurnDirection.Up:
DrawEllipse(g, p, colorBlend, new Rectangle(0, this.Height * (-1), this.Height * 2, this.Height * 2), 90.0f, 90.0f);
break;
case PipeTurnDirection.Down:
DrawEllipse(g, p, colorBlend, new Rectangle(0, 0, this.Height * 2, this.Height * 2), 180.0f, 90.0f);
break;
default:
this.PaintRectangle(g, linearGradientBrush, p, new Rectangle(0, 0, this.Height, this.Height));
break;
}
//右边弯曲
switch (this.pipeTurnRight)
{
case PipeTurnDirection.Up:
DrawEllipse(g, p, colorBlend, new Rectangle(this.Width - this.Height * 2, this.Height*(-1), this.Height * 2, this.Height * 2), 0.0f, 90.0f);
break;
case PipeTurnDirection.Down:
DrawEllipse(g, p, colorBlend, new Rectangle(this.Width - this.Height * 2, 0, this.Height * 2, this.Height * 2), 270.0f, 90.0f);
break;
case PipeTurnDirection.None:
PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Width - this.Height, 0, this.Height, this.Height));
break;
}
//画中间管道的矩形
if(this.Width >= this.Height * 2)
{
PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Height-1, 0, this.Width-this.Height*2+2, this.Height));
}
//画中间的流水
if (isActive)
{
GraphicsPath graphicspath = new GraphicsPath();
//左转弯流水
switch (this.pipeTurnLeft)
{
case PipeTurnDirection.Up:
//这条曲线要注意,是要按照流动的顺序才行
graphicspath.AddArc(new Rectangle(this.Height / 2, this.Height/2 * (-1)-1, this.Height, this.Height), 180.0f, -90.0f);
break;
case PipeTurnDirection.Down:
graphicspath.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180.0f, 90.0f);
break;
default:
graphicspath.AddLine(new Point(0, this.Height/2), new Point(this.Height, this.Height/2));
break;
}
//中间流水
if(this.Width >= this.Height * 2)
{
graphicspath.AddLine(this.Height, this.Height / 2, this.Width - this.Height -1, this.Height / 2);
}
//右转弯流水
switch (this.pipeTurnRight)
{
case PipeTurnDirection.Up:
graphicspath.AddArc(new Rectangle(this.Width - this.Height - this.Height/2, this.Height / 2 * (-1), this.Height, this.Height), 0.0f, 90.0f);
break;
case PipeTurnDirection.Down:
graphicspath.AddArc(new Rectangle(this.Width - this.Height - this.Height/2, this.Height / 2, this.Height, this.Height), 270.0f, 90.0f);
break;
case PipeTurnDirection.None:
graphicspath.AddLine(new Point(this.Width - this.Height, this.Height / 2), new Point(this.Width, this.Height / 2));
break;
}
//画笔要能画虚线的
Pen pen = new Pen(this.colorCenter, PipeWidth);
pen.DashStyle = DashStyle.Custom;
pen.DashPattern = new float[]
{
pipeLength, pipeLength
};
pen.DashOffset = startOffset;
g.DrawPath(pen, graphicspath);
}
}
//这个是自带的,但好像没什么用
//base.OnPaint(e);
}
private void DrawEllipse(Graphics g, Pen p, ColorBlend colorBlend, Rectangle rect, float startAngle, float sweepAngle)
{
//画渐变画刷
GraphicsPath graphicspath = new GraphicsPath();
graphicspath.AddEllipse(rect);
//椭圆的渐变画刷
PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicspath);
pathGradientBrush.CenterPoint = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
pathGradientBrush.InterpolationColors = colorBlend;
//画扇形和沿着扇形的路线
g.FillPie(pathGradientBrush, rect, startAngle, sweepAngle);
g.DrawArc(p, rect, startAngle, sweepAngle);
}
/// <summary>
/// 画中间的矩形
/// </summary>
/// <param name="g"></param>
/// <param name="brush">这个是渐变画刷</param>
/// <param name="pen"></param>
/// <param name="rectangle"></param>
private void PaintRectangle(Graphics g, Brush brush, Pen pen, Rectangle rectangle)
{
g.FillRectangle(brush, rectangle); //矩形填满
switch (this.pipeLineStyle) //矩形周围的线
{
case DirectionStyle.Horizontal:
g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width, rectangle.Y); //上面的线
g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height - 1); //上面的线
break;
case DirectionStyle.Vertical:
g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height); //左边线
g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
break;
default:
break;
}
}
}
}
winform自定义控件-水管
于 2023-07-09 13:06:34 首次发布