Skip to content

Instantly share code, notes, and snippets.

@rqx110
Created August 16, 2017 00:58
Show Gist options
  • Save rqx110/d329aabe5938427dea7865899f89b4a0 to your computer and use it in GitHub Desktop.
Save rqx110/d329aabe5938427dea7865899f89b4a0 to your computer and use it in GitHub Desktop.
winform显示loading图
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace MyControlLibrary
{
public class LoadingProgress : Control
{
private int _spokeNumber = 15;
private int _spokeThickness = 4;
private int _ringThickness = 8;
private int _value = 0;
private int _rotationSpeed = 60;
private Color _baseColor = Color.DodgerBlue;
private Timer _timer;
private bool _active;
private LoadingProgressStyle _style;
[DefaultValue(typeof (LoadingProgressStyle), "0")]
public LoadingProgressStyle Style
{
get
{
return this._style;
}
set
{
if (value == this._style)
return;
this._style = value;
this.Invalidate();
}
}
[DefaultValue(15)]
public int SpokeNumber
{
get
{
return this._spokeNumber;
}
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("SpokeNumber", "不能小于等于0。");
if (this._spokeNumber == value)
return;
this._spokeNumber = value;
this.Invalidate();
}
}
[DefaultValue(4)]
public int SpokeThickness
{
get
{
return this._spokeThickness;
}
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("SpokeThickness", "不能小于等于0。");
if (this._spokeThickness == value)
return;
this._spokeThickness = value;
this.Invalidate();
}
}
[DefaultValue(8)]
public int RingThickness
{
get
{
return this._ringThickness;
}
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("RingThickness", "不能小于等于0。");
if (value == this._ringThickness)
return;
this._ringThickness = value;
this.Invalidate();
}
}
[DefaultValue(60)]
public int RotationSpeed
{
get
{
return this._rotationSpeed;
}
set
{
if (value == this._rotationSpeed)
return;
this._rotationSpeed = value <= 10 ? 10 : value;
this.Timer.Interval = this._rotationSpeed;
}
}
[DefaultValue(false)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool Active
{
get
{
return this._active;
}
set
{
if (this._active == value)
return;
if (value)
this.Start();
else
this.Stop();
}
}
[DefaultValue(typeof (Color), "DodgerBlue")]
public Color BaseColor
{
get
{
return this._baseColor;
}
set
{
this._baseColor = value;
this.Invalidate();
}
}
internal PointF CenterPoint
{
get
{
return new PointF((float) this.Width / 2f, (float) this.Height / 2f);
}
}
protected override Size DefaultSize
{
get
{
return new Size(100, 100);
}
}
private Timer Timer
{
get
{
if (this._timer == null)
{
this._timer = new Timer();
this._timer.Interval = this._rotationSpeed;
this._timer.Tick += new EventHandler(this.TimerTick);
}
return this._timer;
}
}
public LoadingProgress()
{
this.SetStyles();
}
public void Start()
{
if (this._active || this.DesignMode)
return;
this._active = true;
this.Timer.Start();
}
public void Stop()
{
if (!this._active)
return;
this.Timer.Stop();
this._value = 0;
this._active = false;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics graphics = e.Graphics;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
int num = this._value;
switch (this._style)
{
case LoadingProgressStyle.Line:
this.RenderLine(graphics, num);
break;
case LoadingProgressStyle.Circle:
this.RenderCircle(graphics, num);
break;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing || this._timer == null)
return;
this.Stop();
this._timer.Dispose();
this._timer = (Timer) null;
}
private void SetStyles()
{
this.SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.AllPaintingInWmPaint | ControlStyles.CacheText | ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.Opaque, false);
this.UpdateStyles();
}
private void RenderLine(Graphics g, int value)
{
for (int position = 0; position < this.SpokeNumber; ++position)
{
value %= this.SpokeNumber;
using (Pen pen = new Pen(this.GetColor(position), (float) this._spokeThickness))
{
pen.StartCap = LineCap.Round;
pen.EndCap = LineCap.Round;
PointF[] points = this.GetPoints(value);
g.DrawLine(pen, points[0], points[1]);
}
++value;
}
}
private void RenderCircle(Graphics g, int value)
{
for (int position = 0; position < this.SpokeNumber; ++position)
{
value %= this.SpokeNumber;
float num = (float) this.RingThickness * (float) (position + 1) / (float) this.SpokeNumber;
using (SolidBrush solidBrush = new SolidBrush(this.GetColor(position)))
g.FillEllipse((Brush) solidBrush, new RectangleF(this.GetCircleCenterPoint(value), new SizeF(num, num)));
++value;
}
}
private PointF GetCircleCenterPoint(int position)
{
PointF centerPoint = this.CenterPoint;
float num1 = (float) Math.Min(this.Width - 2, this.Height - 2) / 2f - (float) this.RingThickness;
double num2 = this.CaculateAngle(position);
return new PointF(centerPoint.X + num1 * (float) Math.Cos(num2), centerPoint.Y + num1 * (float) Math.Sin(num2));
}
private Color GetColor(int position)
{
float num = (float) byte.MaxValue / (float) this.SpokeNumber;
int alpha = (int) Math.Ceiling((double) (position + 1) * (double) num);
if (alpha > (int) byte.MaxValue)
alpha = (int) byte.MaxValue;
return Color.FromArgb(alpha, this._baseColor);
}
private PointF[] GetPoints(int position)
{
PointF centerPoint = this.CenterPoint;
float num1 = (float) Math.Min(this.Width - 8, this.Height - 8) / 2f;
float num2 = num1 - (float) this.RingThickness;
PointF[] pointFArray = new PointF[2];
double num3 = this.CaculateAngle(position);
pointFArray[0] = new PointF(centerPoint.X + num2 * (float) Math.Cos(num3), centerPoint.Y + num2 * (float) Math.Sin(num3));
pointFArray[1] = new PointF(centerPoint.X + num1 * (float) Math.Cos(num3), centerPoint.Y + num1 * (float) Math.Sin(num3));
return pointFArray;
}
private double CaculateAngle(int position)
{
return Math.PI * (360.0 / (double) this.SpokeNumber * (double) position / 180.0);
}
private void TimerTick(object sender, EventArgs e)
{
this._value = ++this._value % this._spokeNumber;
this.Invalidate();
}
}
}
namespace MyControlLibrary
{
public enum LoadingProgressStyle
{
Line,
Circle,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment