如何沿圆形路径修复进度条渐变?

时间:2013-12-01 21:03:35

标签: c# winforms progress-bar gradient

现在我正在尝试使用渐变沿着圆形路径创建进度条,但渐变不是实心的,颜色之间的空间很小,如screenshot中所示...那么什么是错的以及如何修复它?

    public ExtProgressBar()
    {
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                      ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.UserPaint,
                      true);

        _gradientColorList.Add(Color.Violet);
        _gradientColorList.Add(Color.Indigo);
        _gradientColorList.Add(Color.Blue);
        _gradientColorList.Add(Color.DodgerBlue);

        CreateGradientBrushList(ref _gradientColorList);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Image bmp = new Bitmap(this.Width, this.Height);
        Graphics g = Graphics.FromImage(bmp);
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

        SolidBrush brushBase = new SolidBrush(this.BaseColor); //custom property
        SolidBrush brushBack = new SolidBrush(this.BackColor);
        SolidBrush brushFore = new SolidBrush(this.ForeColor);

        //base ellipse
        g.FillEllipse(brushBase, GetRectangle(0));

        //fallowing code block creates circular gradient
        int i = 0;
        float endAngle = 360f * this.Value / 100 - 90f;
        float sweepAngle = 360f / _gradientBrushList.Count;
        for (float startAngle = -90f; startAngle < endAngle; startAngle += sweepAngle)
        {
            if (i < _gradientBrushList.Count)
            {
                g.FillPie(_gradientBrushList[i++], GetRectangle(0), startAngle, sweepAngle);
            }
        }

        //back ellipse
        g.FillEllipse(brushBack, GetRectangle(this.Thickness));

        //draw value string in center of p-bar
        string value = this.Value.ToString();
        float fontSize = (float)(Math.Min(this.Width - this.Thickness * 2, this.Height - this.Thickness * 2) / 2);
        Font font = new Font("Calibri", (fontSize > 0 ? fontSize : 1), FontStyle.Bold, GraphicsUnit.Pixel);
        SizeF strLen = g.MeasureString(value, font);
        Point strLoc = new Point((int)((this.Width / 2) - (strLen.Width / 2)), (int)((this.Height / 2) - (strLen.Height / 2)));
        g.DrawString(value, font, brushFore, strLoc);

        e.Graphics.DrawImage(bmp, Point.Empty);
    }

    private Rectangle GetRectangle(int offset)
    {
        return new Rectangle(offset, offset, this.Width - offset * 2, this.Height - offset * 2);
    }

    private List<SolidBrush> _gradientBrushList = new List<SolidBrush>();

    private void CreateGradientBrushList(ref List<Color> _gradientColorList)
    {
        List<Color> gradientColorList = new List<Color>();

        foreach (Color color in _gradientColorList)
            gradientColorList.Add(color);

        for (int subdivideCount = 0; subdivideCount <= 3; subdivideCount++) //Smoothness
        {
            int i = 0;
            int gradientColorListCount = gradientColorList.Count - 1;
            while (i < gradientColorListCount)
            {
                gradientColorList.Insert(i + 1, GetMiddleColor(gradientColorList[i], gradientColorList[i + 1]));
                i += 2;
                gradientColorListCount++;
            }
        }

        foreach (Color color in gradientColorList)
            _gradientBrushList.Add(new SolidBrush(color));
    }

    private List<Color> _gradientColorList = new List<Color>();

    public List<Color> GradientColorList
    {
        get
        {
            return _gradientColorList; 
        }
        set
        {
            try
            {
                if (value == null)
                    throw new ArgumentNullException();
                if (value == null || value.Count < 2)
                    throw new Exception("Gradient color list count is less than 2.");
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.Message, "Exception caught", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                _gradientColorList = value;
                CreateGradientBrushList(ref _gradientColorList);
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

还与DrawPie配对使用FillPie。 这是因为FillPie方法仅填充饼图部分的内部,而不填充边框。 代码:

    protected override void OnPaint(PaintEventArgs e)
    {
        Image bmp = new Bitmap(this.Width, this.Height);
        Graphics g = Graphics.FromImage(bmp);
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

        SolidBrush brushBase = new SolidBrush(this.BaseColor); //custom property
        SolidBrush brushBack = new SolidBrush(this.BackColor);
        SolidBrush brushFore = new SolidBrush(this.ForeColor);

        //base ellipse
        g.FillEllipse(brushBase, GetRectangle(0));

        //fallowing code block creates circular gradient
        int i = 0;
        float endAngle = 360f * this.Value / 100 - 90f;
        float sweepAngle = 360f / _gradientBrushList.Count;
        for (float startAngle = -90f; startAngle < endAngle; startAngle += sweepAngle)
        {
            if (i < _gradientBrushList.Count)
            {
                g.DrawPie(_gradientPenList[i++], GetRectangle(0), startAngle, sweepAngle);
                g.FillPie(_gradientBrushList[i++], GetRectangle(0), startAngle, sweepAngle);
            }
        }

        //back ellipse
        g.FillEllipse(brushBack, GetRectangle(this.Thickness));

        //draw value string in center of p-bar
        string value = this.Value.ToString();
        float fontSize = (float)(Math.Min(this.Width - this.Thickness * 2, this.Height - this.Thickness * 2) / 2);
        Font font = new Font("Calibri", (fontSize > 0 ? fontSize : 1), FontStyle.Bold, GraphicsUnit.Pixel);
        SizeF strLen = g.MeasureString(value, font);
        Point strLoc = new Point((int)((this.Width / 2) - (strLen.Width / 2)), (int)((this.Height / 2) - (strLen.Height / 2)));
        g.DrawString(value, font, brushFore, strLoc);

        e.Graphics.DrawImage(bmp, Point.Empty);
    }

    private Rectangle GetRectangle(int offset)
    {
        return new Rectangle(offset, offset, this.Width - offset * 2, this.Height - offset * 2);
    }

    private List<SolidBrush> _gradientBrushList = new List<SolidBrush>();
    private List<Pen> _gradientPenList = new List<Pen>();

    private void CreateGradientBrushList(ref List<Color> _gradientColorList)
    {
        List<Color> gradientColorList = new List<Color>();

        foreach (Color color in _gradientColorList)
            gradientColorList.Add(color);

        for (int subdivideCount = 0; subdivideCount <= 3; subdivideCount++) //Smoothness
        {
            int i = 0;
            int gradientColorListCount = gradientColorList.Count - 1;
            while (i < gradientColorListCount)
            {
                gradientColorList.Insert(i + 1, GetMiddleColor(gradientColorList[i], gradientColorList[i + 1]));
                i += 2;
                gradientColorListCount++;
            }
        }

        foreach (Color color in gradientColorList)
        {
            _gradientBrushList.Add(new SolidBrush(color));
            _gradientPenList.Add(new Pen(color));
        }
    }