Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created March 14, 2018 22:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/0793f5fd28e00de6198989d47135bf92 to your computer and use it in GitHub Desktop.
Save mjs3339/0793f5fd28e00de6198989d47135bf92 to your computer and use it in GitHub Desktop.
C# Circular Progress Bar with Percentage
/// <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