I would like to achieve semi-circle progress bars but I don't have enough experience in visual studio, I did find a circular progress bar Nuget pack that is possible to do full circle but I couldn't find a way to succeed in making half one (even tried to modify source code of CircularProgressBar Nuget pack), is there anyone can give tip or way of achieving that. Thanks.
CodePudding user response:
You can subclass and create a custom semicircle progress control. All what you need to do is a 180°-based calculation and drawing rather than a 360°.
Derive a new class from the Label
control and import:
using System;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;
And encapsulate:
- The key properties of a progress control,
Value
,Minimum
, andMaximum
. - Properties used to draw the progress, track size, track and value colors.
- custom event to notify a subscriber with the value changes.
- The drawing routine which calls the
Graphics.DrawArc
method to draw both, the track and value arcs.
[DesignerCategory("Code")]
[DefaultProperty("Value")]
[DefaultEvent("ValueChanged")]
[ToolboxItem(typeof(ToolboxItem))]
[ToolboxBitmap(typeof(ProgressBar))]
public class SemiCircleProgress : Label
{
#region ctor
public SemiCircleProgress() : base() { }
#endregion
#region Properties
private int _value;
[DefaultValue(0)]
public int Value
{
get => _value;
set
{
if (_value != value)
{
_value = value < Minimum ? Minimum : value > Maximum ? Maximum : value;
Invalidate();
OnValueChanged(new EventArgs());
}
}
}
private int _min;
[DefaultValue(0)]
public int Minimum
{
get => _min;
set
{
if (_min != value)
{
_min = Math.Max(value, 0);
if (value > _value) _value = value;
if (value > _max) _max = value;
Invalidate();
}
}
}
private int _max = 100;
[DefaultValue(100)]
public int Maximum
{
get => _max;
set
{
if (_max != value)
{
if (value < 1) value = 1;
if (value < _value) _value = value;
_max = value;
Invalidate();
}
}
}
private int _trackSize = 10;
[DefaultValue(10)]
public int TrackSize
{
get => _trackSize;
set
{
if (_trackSize != value)
{
_trackSize = value;
Invalidate();
}
}
}
private Color _trackColor = Color.Gray;
[DefaultValue(typeof(Color), "Gray")]
public Color TrackColor
{
get => _trackColor;
set
{
if (_trackColor != value)
{
_trackColor = value;
Invalidate();
}
}
}
private Color _valueColor = Color.FromArgb(255, 128, 0);
[DefaultValue(typeof(Color), "255, 128, 0")]
public Color ValueColor
{
get => _valueColor;
set
{
if (_valueColor != value)
{
_valueColor = value;
Invalidate();
}
}
}
private bool _showValue;
[DefaultValue(false)]
public bool ShowValue
{
get => _showValue;
set
{
if (_showValue != value)
{
_showValue = value;
Invalidate();
}
}
}
protected override Size DefaultSize => new Size(100, 100);
#endregion
#region Paint
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
var r = new Rectangle(_trackSize, _trackSize,
Math.Max(_trackSize * 2, Width - _trackSize * 2),
Math.Max(_trackSize * 2, (Height - _trackSize * 2) * 2));
using (var pnTrack = new Pen(_trackColor, _trackSize))
{
g.Clear(BackColor);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.DrawArc(pnTrack, r, 180, 180);
if (Value > Minimum)
{
var val = (int)Math.Round(180d / Maximum * Value);
pnTrack.Color = _valueColor;
// pnTrack.Width -= 2; // uncomment and try...
g.DrawArc(pnTrack, r, 180, val);
}
}
if (_showValue)
{
TextRenderer.DrawText(g, Value.ToString(), Font, r, ForeColor,
TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
}
}
#endregion
#region Events
public event EventHandler ValueChanged;
protected virtual void OnValueChanged(EventArgs e) =>
ValueChanged?.Invoke(this, e);
#endregion
}
ToDo : Hide the not used properties of the base class:
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text { get => base.Text; set => base.Text = value; }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new Image Image { get; set; }
// ...etc.