Visual Studio 半圆进度条

Visual Studio Half Circle Progress Bars

我想实现半圆形进度条,但我没有足够的经验visual studio,我确实找到了一个圆形进度条 Nuget 包,它可以做完整的圆形,但我做不到'找不到成功制作一半的方法(甚至尝试修改 CircularProgressBar Nuget 包的源代码),是否有人可以提供提示或实现方法。谢谢

What circular progress bar Nuget pack offers

Half-circular progress bar that I am trying to implement on my design

这可能不是最好的解决方案,但您可以在圆形进度条项目的下半部分添加一个面板。然后将 StartAngle 设置为 180,将 Maximum 设置为最大可达值的两倍。这里有一小段示例(快速而肮脏):

您可以子class 并创建自定义半圆进度 控件。你要做的只是180°的计算和绘图,而不是360°。

Label 控件导出新的 class 并导入:

using System;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;

并封装:

  • 进度控件的关键属性,ValueMinimumMaximum
  • 用于绘制进度、轨道大小、轨道和值颜色的属性。
  • 用于通知订阅者值更改的自定义事件。
  • 调用 Graphics.DrawArc 方法绘制轨道和值弧的绘图例程。
[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 : 隐藏基地不使用的属性 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.