public partial class LoadProgressExt : Control { /// <summary> /// 圆总角度 /// </summary> private const double circleAngle = 360; private const int L_innerCircleRadius = 8; private const int L_outerCircleRadius = 16; private const int L_lineNumber = 10; private const int L_lineThickness = 4; private const int D_innerCircleRadius = 12; private const int D_outerCircleRadius = 18; private const int D_lineNumber = 8; private const int D_lineThickness = 5; private AnimationTimer _Animation; private int loadProgressValue;//进度条值 private Point centerPoint;//控件中心坐标 /// <summary> /// 每条直线颜色 /// </summary> private List<Color> lineColors; /// <summary> /// 每条直线角度 /// </summary> private List<double> lineAngles; #region 属性 private Color progressColor = Color.OliveDrab; /// <summary> /// 进度条颜色 /// </summary> [Description("进度条颜色")] [DefaultValue(typeof(Color), "OliveDrab")] public Color ProgressColor { get { return this.progressColor; } set { this.progressColor = value; this.lineColors = GetLinesColors(this.progressColor, this.active); this.Invalidate(); } } private int innerCircleRadius = 8; /// <summary> /// 内圆半径 /// </summary> [Description("内圆半径")] [DefaultValue(8)] public int InnerCircleRadius { get { return this.innerCircleRadius; } set { if (value >= 0) { this.innerCircleRadius = value; this.Invalidate(); } } } private int outerCircleRadius = 16; /// <summary> /// 外围半径 /// </summary> [Description("外围半径")] [DefaultValue(16)] public int OuterCircleRadius { get { return this.outerCircleRadius; } set { if (value > 0) { this.outerCircleRadius = value; this.Invalidate(); } } } private int lineNumber = 10; /// <summary> /// 直线数量 /// </summary> [Description("直线数量")] [DefaultValue(10)] public int LineNumber { get { return this.lineNumber; } set { if (this.lineNumber != value && this.lineNumber > 0) { lineNumber = value; this.lineColors = this.GetLinesColors(this.progressColor, this.active); this.lineAngles = this.GetLinesAngles(); this.Invalidate(); } } } private bool active = false; /// <summary> /// 加载中 /// </summary> [Description("加载中")] [DefaultValue(false)] public bool Active { get { return this.active; } set { this.active = value; if (value) { this.loadProgressValue = 0; this.lineColors = this.GetLinesColors(this.progressColor, this.active); this._Animation.Start(true, 0.0); } else { this._Animation.Stop(); } } } private bool isText = false; /// <summary> /// 是否显示文本 /// </summary> [Description("是否显示文本")] [DefaultValue(false)] public bool IsText { get { return this.isText; } set { this.isText = value; this.Invalidate(); } } private int lineThickness = 4; /// <summary> /// 直线粗细程度 /// </summary> [Description("直线粗细程度")] [DefaultValue(4)] public int LineThickness { get { return this.lineThickness; } set { if (value > 0) { this.lineThickness = value; this.Invalidate(); } } } /// <summary> /// 动画速度 /// </summary> [Description("动画速度")] [DefaultValue(100)] public int AnimationSpeed { get { return this._Animation.Interval; } set { this._Animation.Interval = value; } } private LoadProgressType progressType = LoadProgressType.Line; /// <summary> /// 加载进度条类型 /// </summary> [Description("加载进度条类型")] [DefaultValue(typeof(LoadProgressType), "Line")] public LoadProgressType ProgressType { get { return this.progressType; } set { this.progressType = value; this.SetSetting(value); this.lineColors = GetLinesColors(this.progressColor, this.Active); this.lineAngles = GetLinesAngles(); this.Invalidate(); } } #endregion public LoadProgressExt() { this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.ForeColor = Color.White; this.centerPoint = new Point(this.Width / 2, this.Height / 2); this.lineColors = GetLinesColors(this.progressColor, this.Active); this.lineAngles = GetLinesAngles(); this._Animation = new AnimationTimer(this, new AnimationOptions()); this._Animation.Interval = 100; this._Animation.Options.AlwaysTime = true; this._Animation.AnimationIng += new AnimationTimer.AnimationHandel(this.Animation_AnimationIng); } /// <summary> /// 大小更改 /// </summary> /// <param name="e"></param> protected override void OnResize(EventArgs e) { base.OnResize(e); this.centerPoint = new Point(this.Width / 2, this.Height / 2); } /// <summary> /// 默认大小 /// </summary> protected override Size DefaultSize { get { return new Size(40, 40); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (this.lineNumber > 0) { e.Graphics.SmoothingMode = SmoothingMode.HighQuality; e.Graphics.CompositingQuality = CompositingQuality.HighQuality; e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; int intPosition = this.loadProgressValue; for (int i = 0; i < this.lineNumber; i++) { intPosition = intPosition % this.lineNumber; PointF start = GetCoordinate(this.centerPoint, this.innerCircleRadius, this.lineAngles[intPosition]); PointF end = GetCoordinate(this.centerPoint, this.outerCircleRadius, this.lineAngles[intPosition]); switch (this.ProgressType) { case LoadProgressType.Line: { using (Pen pen = new Pen(lineColors[i], this.lineThickness)) { pen.StartCap = LineCap.Round; pen.EndCap = LineCap.Round; e.Graphics.DrawLine(pen, start, end); } break; } case LoadProgressType.Dot: { double inner_outer = Math.Sqrt(Math.Pow((end.X - start.X), 2) + Math.Pow((end.Y - start.Y), 2));//内外圆距离 float wh = (float)Math.Sqrt(Math.Pow(inner_outer, 2) / 2.0);//圆形外边正方形边长 PointF startPoint = new PointF(start.X + (float)((end.X - start.X) / 2.0), start.Y + (float)((end.Y - start.Y) / 2.0)); startPoint = new PointF(startPoint.X - (float)(wh / 2.0), startPoint.Y - (float)(wh / 2.0));//圆形外边正方形起始坐标 using (Pen pen = new Pen(lineColors[i], this.lineThickness)) { e.Graphics.DrawEllipse(pen, new RectangleF(startPoint, new SizeF(wh, wh))); } break; } } intPosition++; } if (this.isText && !String.IsNullOrWhiteSpace(this.Text)) { SolidBrush sb = new SolidBrush(this.ForeColor); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Far; sf.Trimming = StringTrimming.EllipsisCharacter; SizeF size = e.Graphics.MeasureString(this.Text, this.Font); e.Graphics.DrawString(this.Text, this.Font, sb, new RectangleF(0.0f, e.Graphics.ClipBounds.Bottom - size.Height, (float)this.Width, size.Height), sf); } } } protected void Animation_AnimationIng(object sender, AnimationEventArgs e) { this.loadProgressValue = (++this.loadProgressValue) % this.lineNumber; this.Invalidate(); } /// <summary> /// 计算每条直线颜色 /// </summary> /// <param name="lineColor">直线颜色</param> /// <param name="isTransparent">是否启用颜色透明度增量</param> /// <returns></returns> private List<Color> GetLinesColors(Color lineColor, bool isTransparent) { List<Color> colorsList = new List<Color>(); byte transparent = 0;//颜色透明度 byte transparentIncrement = (byte)(byte.MaxValue / this.LineNumber);//颜色透明度增量 for (int i = 0; i < this.LineNumber; i++) { Color c = lineColor; if (isTransparent) { if (i > 0) { transparent += transparentIncrement; if (transparent > byte.MaxValue) { transparent = byte.MaxValue; } c = Color.FromArgb(transparent, Math.Min(lineColor.R, byte.MaxValue), Math.Min(lineColor.G, byte.MaxValue), Math.Min(lineColor.B, byte.MaxValue)); } } colorsList.Add(c); } return colorsList; } /// <summary> /// 计算每条直线角度 /// </summary> /// <returns></returns> private List<double> GetLinesAngles() { List<double> lineAnglesList = new List<double>(); double avgAngle = (double)circleAngle / (double)this.lineNumber; for (int i = 0; i < this.lineNumber; i++) { lineAnglesList.Add((i + 1) * avgAngle); } return lineAnglesList; } /// <summary> /// 已中心根据角度获取圆环上对应坐标 /// </summary> /// <param name="_centerPoint">中心</param> /// <param name="_radius">圆环半径</param> /// <param name="_angle">角度</param> /// <returns>圆环上对应坐标</returns> private PointF GetCoordinate(PointF _centerPoint, int _radius, double _angle) { //经纬度转化成弧度(弧度=经纬度 * Math.PI / 180d); double dblAngle = _angle * Math.PI / (circleAngle / 2); return new PointF(_centerPoint.X + _radius * (float)Math.Cos(dblAngle), _centerPoint.Y + _radius * (float)Math.Sin(dblAngle)); } /// <summary> /// 设置加载进度条类型 /// </summary> /// <param name="_progressType"></param> private void SetSetting(LoadProgressType _progressType) { switch (this.ProgressType) { case LoadProgressType.Line: { this.innerCircleRadius = L_innerCircleRadius; this.outerCircleRadius = L_outerCircleRadius; this.lineNumber = L_lineNumber; this.lineThickness = L_lineThickness; break; } case LoadProgressType.Dot: { this.innerCircleRadius = D_innerCircleRadius; this.outerCircleRadius = D_outerCircleRadius; this.lineNumber = D_lineNumber; this.lineThickness = D_lineThickness; break; } } } } /// <summary> /// 加载进度条类型 /// </summary> public enum LoadProgressType { /// <summary> /// 直线 /// </summary> Line, /// <summary> /// 圆球 /// </summary> Dot }