Created
August 16, 2017 00:58
-
-
Save rqx110/d329aabe5938427dea7865899f89b4a0 to your computer and use it in GitHub Desktop.
winform显示loading图
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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