Created
March 14, 2018 22:35
-
-
Save mjs3339/0793f5fd28e00de6198989d47135bf92 to your computer and use it in GitHub Desktop.
C# Circular Progress Bar with Percentage
This file contains 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
/// <summary> | |
/// Circular Progress bar with percentage | |
/// </summary> | |
public class CircularProgressBar : Control | |
{ | |
public enum graphtypes | |
{ | |
Standard, | |
Spin | |
} | |
public enum spinspeed | |
{ | |
Slow, | |
Medium, | |
Fast | |
} | |
public enum startingpoints | |
{ | |
North = 270, | |
East = 0, | |
South = 90, | |
West = 180 | |
} | |
private readonly IContainer components = null; | |
private Pen _backgroundpen = new Pen(Color.Silver, 5); | |
private int _barwidth = 5; | |
private Color _bgcolor = Color.Silver; | |
private bool _enablespin; | |
private Color _fontcolor = Color.Black; | |
private float _fontreduction = 1; | |
private Color _forecolor = Color.DodgerBlue; | |
private Pen _foregroundpen = new Pen(Color.DodgerBlue, 5); | |
private graphtypes _graphtype = graphtypes.Standard; | |
private float _percent; | |
private float _spincounter; | |
private spinspeed _spinspeed = spinspeed.Medium; | |
private DateTime _spinstarttime; | |
private float _spinstep = 6; | |
private float _spinsweepdegree = 45; | |
private startingpoints _stratingpoint = startingpoints.North; | |
private Pen _textpen = new Pen(Color.Black) {Brush = new SolidBrush(Color.FromArgb(255, Color.Black))}; | |
private readonly MMTimer _timer; | |
private Font _writingFont; | |
public CircularProgressBar() | |
{ | |
InitializeComponent(); | |
SetStyle(ControlStyles.OptimizedDoubleBuffer | |
| ControlStyles.AllPaintingInWmPaint | |
| ControlStyles.ResizeRedraw | |
| ControlStyles.UserPaint | |
| ControlStyles.SupportsTransparentBackColor, true); | |
_timer = new MMTimer(); | |
_timer.Interval = 50; | |
_timer.Elapsed += _timer_Elapsed; | |
} | |
/// <summary> | |
/// Enables and resets the spin time display | |
/// </summary> | |
[Description("Enables and resets the spin time display")] | |
public bool EnableSpin | |
{ | |
get => _enablespin; | |
set | |
{ | |
_enablespin = value; | |
_timer.Enabled = value; | |
_spinstarttime = DateTime.Now; | |
try | |
{ | |
Invalidate(true); | |
} | |
catch | |
{ | |
} | |
} | |
} | |
/// <summary> | |
/// Sets the sweep degree default=45 maximum=180, minimum=1 | |
/// </summary> | |
[Description("Sets the sweep degree default=45 maximum=180, minimum=1")] | |
public float SpinSweepDegree | |
{ | |
get => _spinsweepdegree; | |
set | |
{ | |
_spinsweepdegree = value; | |
if (_spinsweepdegree > 180) | |
_spinsweepdegree = 180; | |
if (_spinsweepdegree < 1) | |
_spinsweepdegree = 1; | |
if (_spinsweepdegree < _spinstep) | |
_spinstep = _spinsweepdegree; | |
else | |
switch (_spinspeed) | |
{ | |
case spinspeed.Slow: | |
_spinstep = 3; | |
_timer.Interval = 80; | |
break; | |
case spinspeed.Medium: | |
_spinstep = 6; | |
_timer.Interval = 50; | |
break; | |
case spinspeed.Fast: | |
_spinstep = 8; | |
_timer.Interval = 20; | |
break; | |
} | |
Invalidate(true); | |
} | |
} | |
/// <summary> | |
/// Sets the spin speed while graph type is set to spin | |
/// </summary> | |
[Description("Sets the spin speed while graph type is set to spin")] | |
public spinspeed SpinSpeed | |
{ | |
get => _spinspeed; | |
set | |
{ | |
_timer.Enabled = _enablespin = false; | |
_spinspeed = value; | |
switch (value) | |
{ | |
case spinspeed.Slow: | |
_spinstep = 3; | |
_timer.Interval = 80; | |
break; | |
case spinspeed.Medium: | |
_spinstep = 6; | |
_timer.Interval = 50; | |
break; | |
case spinspeed.Fast: | |
_spinstep = 8; | |
_timer.Interval = 20; | |
break; | |
} | |
Invalidate(true); | |
} | |
} | |
/// <summary> | |
/// Sets the graph type and sets the animation timer | |
/// </summary> | |
[Description("Sets the graph type and sets the animation timer")] | |
public graphtypes GraphType | |
{ | |
get => _graphtype; | |
set | |
{ | |
_graphtype = value; | |
EnableSpin = false; | |
try | |
{ | |
Invalidate(true); | |
} | |
catch | |
{ | |
} | |
} | |
} | |
/// <summary> | |
/// Sets the starting angle of rotation North=up,east=right,south=down,west=left | |
/// </summary> | |
[Description("Sets the starting angle of rotation North=up,east=right,south=down,west=left")] | |
public startingpoints StartingPoint | |
{ | |
get => _stratingpoint; | |
set | |
{ | |
_stratingpoint = value; | |
Invalidate(true); | |
} | |
} | |
/// <summary> | |
/// Sets the size reduction in font size i.e. .5 would be 1/2 the font size. | |
/// </summary> | |
[Description("Sets the size reduction in font size i.e. .5 would be 1/2 the font size.")] | |
public float FontReduction | |
{ | |
get => _fontreduction; | |
set | |
{ | |
_fontreduction = value; | |
Invalidate(true); | |
} | |
} | |
/// <summary> | |
/// Gets or Sets Font color for drawing text | |
/// </summary> | |
[Description("Gets or Sets Font color for drawing text")] | |
public Color FontColor | |
{ | |
get => _fontcolor; | |
set | |
{ | |
_fontcolor = value; | |
_textpen = new Pen(_fontcolor) {Brush = new SolidBrush(Color.FromArgb(255, _fontcolor))}; | |
Invalidate(true); | |
} | |
} | |
/// <summary> | |
/// Gets or Sets progress bar width | |
/// </summary> | |
[Description("Gets or Sets progress bar width")] | |
public int Barwidth | |
{ | |
get => _barwidth; | |
set | |
{ | |
_barwidth = value; | |
if (_barwidth > Width * .48) | |
_barwidth = (int) (Width * .48); | |
_backgroundpen = new Pen(_bgcolor, _barwidth); | |
_foregroundpen = new Pen(_forecolor, _barwidth); | |
Invalidate(); | |
} | |
} | |
/// <summary> | |
/// Gets or Sets progress bar drawing color | |
/// </summary> | |
[Description("Gets or Sets progress bar drawing color")] | |
public override Color ForeColor | |
{ | |
get => _forecolor; | |
set | |
{ | |
_forecolor = value; | |
_foregroundpen = new Pen(_forecolor, _barwidth); | |
Invalidate(); | |
} | |
} | |
/// <summary> | |
/// Gets or Sets progress bar background drawing color | |
/// </summary> | |
[Description("Gets or Sets progress bar background drawing color")] | |
public Color BGColor | |
{ | |
get => _bgcolor; | |
set | |
{ | |
_bgcolor = value; | |
_backgroundpen = new Pen(_bgcolor, _barwidth); | |
Invalidate(); | |
} | |
} | |
/// <summary> | |
/// Gets or Sets percentage value | |
/// </summary> | |
[Description("Gets or Sets percentage value")] | |
public float Percent | |
{ | |
get => _percent; | |
set | |
{ | |
_percent = value / 100; | |
Invalidate(); | |
} | |
} | |
private void _timer_Elapsed(object sender, EventArgs e) | |
{ | |
_timer.Enabled = false; | |
_spincounter = _spincounter + _spinstep; | |
if (_spincounter >= 360) | |
_spincounter = 0; | |
try | |
{ | |
Invalidate(true); | |
} | |
catch | |
{ | |
} | |
_timer.Enabled = true; | |
} | |
protected override void OnResize(EventArgs eventargs) | |
{ | |
if (Width < 20 || Height < 20) | |
Width = Height = 20; | |
Width = Height; | |
if (_barwidth > Width * .48) | |
_barwidth = (int) (Width * .48); | |
if (_barwidth < 1) | |
_barwidth = 1; | |
Invalidate(true); | |
base.OnResize(eventargs); | |
} | |
protected override void OnPaint(PaintEventArgs e) | |
{ | |
var g = e.Graphics; | |
_writingFont = Font; | |
g.InterpolationMode = InterpolationMode.HighQualityBicubic; | |
g.SmoothingMode = SmoothingMode.HighQuality; | |
g.CompositingQuality = CompositingQuality.HighQuality; | |
var dr = _barwidth / 2 + 2; | |
var rec = Rectangle.Inflate(ClientRectangle, -dr, -dr); | |
g.DrawArc(_backgroundpen, rec, 0f, 360.0f); | |
if (_graphtype == graphtypes.Standard) | |
{ | |
var sa = 360.0f * _percent; | |
if (sa > 1) | |
g.DrawArc(_foregroundpen, rec, (float) _stratingpoint, sa); | |
using (_writingFont = new Font(_writingFont.Name, (float) (ClientRectangle.Height - 4) / 4 * _fontreduction, _writingFont.Style, GraphicsUnit.Point)) | |
{ | |
var st = $"{Percent * 100:0.0}"; | |
var s = e.Graphics.MeasureString(st, _writingFont); | |
e.Graphics.DrawString(st, _writingFont, _textpen.Brush, Width / 2f - s.Width / 2f, ClientRectangle.Height / 2f - s.Height / 2f); | |
} | |
using (_writingFont = new Font(_writingFont.Name, (float) (ClientRectangle.Height - 4) / 6 * _fontreduction, _writingFont.Style, GraphicsUnit.Point)) | |
{ | |
var s1 = e.Graphics.MeasureString("%", _writingFont); | |
e.Graphics.DrawString("%", _writingFont, _textpen.Brush, Width / 2f - s1.Width / 2f, ClientRectangle.Height / 2f + s1.Height / 2); | |
} | |
} | |
else | |
{ | |
var sp = _spincounter; | |
var ep = _spinsweepdegree; | |
g.DrawArc(_foregroundpen, rec, sp, ep); | |
var elapsedseconds = DateTime.Now.Subtract(_spinstarttime); | |
if (elapsedseconds.TotalSeconds > 900) | |
{ | |
_spinstarttime = DateTime.Now; | |
elapsedseconds = DateTime.Now.Subtract(_spinstarttime); | |
} | |
var st = $"{elapsedseconds.TotalSeconds:00}"; | |
using (_writingFont = new Font(_writingFont.Name, (float) (ClientRectangle.Height - 4) / 4 * _fontreduction, _writingFont.Style, GraphicsUnit.Point)) | |
{ | |
var s = e.Graphics.MeasureString(st, _writingFont); | |
e.Graphics.DrawString(st, _writingFont, _textpen.Brush, Width / 2f - s.Width / 2f, ClientRectangle.Height / 2f - s.Height / 2f); | |
} | |
using (_writingFont = new Font(_writingFont.Name, (float) (ClientRectangle.Height - 4) / 8 * _fontreduction, _writingFont.Style, GraphicsUnit.Point)) | |
{ | |
var s1 = e.Graphics.MeasureString("Sec", _writingFont); | |
e.Graphics.DrawString("Sec", _writingFont, _textpen.Brush, Width / 2f - s1.Width / 2f, ClientRectangle.Height / 2f + s1.Height / 2); | |
} | |
} | |
base.OnPaint(e); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (disposing) | |
components?.Dispose(); | |
base.Dispose(disposing); | |
} | |
private void InitializeComponent() | |
{ | |
SuspendLayout(); | |
Name = "CircularProgressBar"; | |
Size = new Size(100, 100); | |
ResumeLayout(false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment