当前位置:首页 > WinForm

WinForm重绘进度条ProgressBar显示百分比进度

发表于 2017-05-14 13:45

本篇文章教大家怎么重绘ProgressBar,效果图如下:

image.png


此控件功能比较单一,不用多少代码就可以实现。全部如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Windite.Windows.Forms
{
    public partial class ProgressBar : System.Windows.Forms.ProgressBar
    {

        private bool _bolUseMetroStyle = false;
        private MetroColorTable _objMetroColorTable = null;

        private bool _showPercentage = false;
        private Font _font = null;

        private Color _themeColor = Color.FromArgb(22, 154, 218);

        public ProgressBar()
        {
            InitializeComponent();

            SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
        }

        [DefaultValue(false)]
        public bool UseMetroStyle
        {
            get { return this._bolUseMetroStyle; }
            set
            {
                if (this._bolUseMetroStyle != value)
                {
                    this._bolUseMetroStyle = value;
                    this.Invalidate();
                }
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(null)]
        public MetroColorTable MetroColorTable
        {
            get { return this._objMetroColorTable != null ? this._objMetroColorTable : Windite.Windows.Forms.Framework.MetroColorTable; }
            set
            {
                this._objMetroColorTable = value;
                this.Invalidate();
            }
        }

        [DefaultValue(false)]
        public bool ShowPercentage
        {
            get { return _showPercentage; }
            set { _showPercentage = value; }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            Graphics g = pe.Graphics;

            ControlPaint.DrawBorder(g, this.ClientRectangle, Color.DarkGray, ButtonBorderStyle.Solid);

            int total = this.Maximum - this.Minimum;
            int current = this.Value - this.Minimum;
            Rectangle currentRect = new Rectangle();
            int percentage = this.GetPercentage();

            if (current < 0)
            {
                current = 0;
            }
            if(current > total)
            {
                current = total;
            }

            currentRect.X = 1;
            currentRect.Y = 1;
            currentRect.Width = (int)((double)percentage / (double)100 * (this.Width - 2));
            currentRect.Height = this.Height - 2;

            using(SolidBrush objBrush = new SolidBrush (_themeColor/*this.MetroColorTable.ThemeColor*/))
            {
                g.FillRectangle(objBrush, currentRect);
            }

            if (this.ShowPercentage)
            {
                StringFormat strFormat = new StringFormat ();
                string percentageText = percentage.ToString() + "%";
                SizeF percentageTextSize = SizeF.Empty;
                RectangleF percentageTextRect = RectangleF.Empty;

                strFormat.Alignment= StringAlignment.Near;
                strFormat.LineAlignment = StringAlignment.Center;
                strFormat.FormatFlags = StringFormatFlags.LineLimit;
                strFormat.Trimming = StringTrimming.None;

                percentageTextSize = g.MeasureString(percentageText,this.GetFont(),this.Width,strFormat);

                percentageTextRect.X = (this.Width - percentageTextSize.Width)/2;
                percentageTextRect.Y = 0;
                percentageTextRect.Width = percentageTextSize.Width;
                percentageTextRect.Height = this.Height;
                
                if (percentageTextRect.Left >= currentRect.Right)
                {
                    strFormat.Alignment = StringAlignment.Center;
                    using (SolidBrush objBrushText = new SolidBrush(Color.Black))
                    {
                        g.DrawString(percentageText, this.GetFont(), objBrushText, this.ClientRectangle, strFormat);
                    }
                }
                else if (currentRect.Right >= percentageTextRect.Right)
                {
                    strFormat.Alignment = StringAlignment.Center;
                    using (SolidBrush objBrushText = new SolidBrush(Color.White))
                    {
                        g.DrawString(percentageText, this.GetFont(), objBrushText, this.ClientRectangle, strFormat);
                    }
                }
                else
                {
                    using (SolidBrush objBrushText = new SolidBrush(Color.Black))
                    {
                        g.DrawString(percentageText, this.GetFont(), objBrushText, percentageTextRect, strFormat);
                    }

                    Bitmap bitmapText = new Bitmap((int)percentageTextRect.Width+1,(int)percentageTextRect.Height);
                    Graphics gTemp = Graphics.FromImage(bitmapText);

                    gTemp.Clear(_themeColor/*this.MetroColorTable.ThemeColor*/);

                    using (SolidBrush objBrushText = new SolidBrush(Color.White))
                    {
                        gTemp.DrawString(percentageText, this.GetFont(), objBrushText, new RectangleF(0, 0, bitmapText.Width, bitmapText.Height), strFormat);
                    }
                    g.DrawImage(bitmapText, new RectangleF(percentageTextRect.Left, 0, currentRect.Right - percentageTextRect.Left, this.Height), new RectangleF(0, 0, currentRect.Right - percentageTextRect.Left, this.Height),GraphicsUnit.Pixel);

                    gTemp.Dispose();
                    bitmapText.Dispose();
                }
            }
        }

        private int GetPercentage()
        {
            int total = this.Maximum - this.Minimum;
            int current = this.Value - this.Minimum;

            if (current < 0)
            {
                current = 0;
            }
            if (current > total)
            {
                current = total;
            }

            return (int)Math.Ceiling((double)current / total * 100);
        }

        private Font GetFont()
        {
            if (this._font == null)
            {
                this._font = Windite.Utilities.Fonts.GetFont(FontTypes.Default, 9);
            }
            return this._font;
        }

    }
}


重绘时,主要有一个小功能需要一点点技巧:

本控件增加了显示百分比的功能,通过ShowPercentage属性控制显示与否,这个.NET自带进度条所没有的。我们需要达到一种效果就是当进度条到达显示百分比的位置时,在进度条上的百分比部分显示为白色,在进度条之外的百分比显示为黑色。如图:

image.png

难点在于一个字符就要一半显现白色,一半显示黑色。实现方法是,先把所有百分比用黑色画出来,然后在上面覆盖白色的一部分,白色的一部分需要先在内存Bitmap中画好,再将Bitmap画到进度条的Graphics上,注意要控制好源区域和目标区域。实现代码:

using (SolidBrush objBrushText = new SolidBrush(Color.Black))
                    {
                        g.DrawString(percentageText, this.GetFont(), objBrushText, percentageTextRect, strFormat);
                    }

                    Bitmap bitmapText = new Bitmap((int)percentageTextRect.Width+1,(int)percentageTextRect.Height);
                    Graphics gTemp = Graphics.FromImage(bitmapText);

                    gTemp.Clear(_themeColor/*this.MetroColorTable.ThemeColor*/);

                    using (SolidBrush objBrushText = new SolidBrush(Color.White))
                    {
                        gTemp.DrawString(percentageText, this.GetFont(), objBrushText, new RectangleF(0, 0, bitmapText.Width, bitmapText.Height), strFormat);
                    }
                    g.DrawImage(bitmapText, new RectangleF(percentageTextRect.Left, 0, currentRect.Right - percentageTextRect.Left, this.Height), new RectangleF(0, 0, currentRect.Right - percentageTextRect.Left, this.Height),GraphicsUnit.Pixel);

                    gTemp.Dispose();
                    bitmapText.Dispose();



本文章由创风网原创,转载请注明出处:http://www.windite.com/article/details/j0nobe12