简单实现在标准的ProgressBar上绘制百分比

来源:互联网 发布:新东方网络课程好吗? 编辑:程序博客网 时间:2024/05/17 08:54

  在很久(1~2年)以前,我就在开始尝试在标准的ProgressBar上绘制百分比,主要是想重写OnPaint方法来实现,但无一例外,全都失败了。在网络上想找相关方法,找到都是一是与我的想法相同(重写OnPaint),二是自己重新写一个ProgressBar(包括在CodeProject网站上也是这个方法),然而,这些方法都有很大的缺陷:不能使ProgressBar随着Windows的主题变化而变化。并没有找到可行的方法在标准的ProgressBar上实现百分比。

  2个月前,我将注意力转到VC++方向。子类化了CProgressCtrl类,在子类中的OnPaint事件中绘制百分比,这个做法竟然通过了,实现了在标准的ProgressBar上绘制百分比!于是,我想将这个做法转到.net中实现,但怎样实现呢?不能简单的在OnPaint中绘制(之前已验证这个方法是不行的了)。我认真的想了想在VC++中的实现原理,其实OnPaint事件也必须要通过消息来引发的(截获WM_PAINT消息,引发OnPaint事件),如果在.net中直接截获WM_PAINT消息并绘制百分比可不可以达到相同的效果?实验证明,我这个想法是可行的,至此,我终于在.net中用简单的方法实现了在标准的ProgressBar上绘制百分比。

  在.net中的ProgressBar中,一般情况下重写OnPaint方法时,在运行期间这个方法不会被执行,只有用ProgressBar中的SetStyle方法将UserPaint设为true时,OnPaint才会被执行,但是,这时ProgressBar中的原来的视觉效果完全消失了,这不符合初衷。截获WM_PAINT消息,同时将百分比绘制在控件上,就达到了目的。

下面给出代码:

在PercentProgress.cs文件中:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;namespace ControlLibrary{    public enum Correct    {        None,        One    }    public partial class PercentProgress : ProgressBar    {        private const int WM_PAINT = 0x000f;        private Font font = new Font("宋体", 12);        /// <summary>        /// 控件上百分比的字体         /// </summary>        [Description("控件上百分比的字体")]        [Category("外观")]        [RefreshProperties(RefreshProperties.All)]        public Font TextFont        {            get { return this.font; }            set { this.font = value; }        }        private string text = "0%";        private Color percentColor = Color.Black;        /// <summary>        /// 百分比字体的颜色         /// </summary>        [Description("百分比字体的颜色")]        [Category("外观")]        [RefreshProperties(RefreshProperties.All)]        public Color PercentColor        {            get { return this.percentColor; }            set { this.percentColor = value; }        }        private Correct percentStyle = Correct.One;        /// <summary>        /// 百分比的精确类型.如果None表示只用整型.如果One保留一位小数.        /// </summary>        [Description("百分比的精确类型./n如果None表示只用整型./n如果One保留一位小数.")]        [Category("外观")]        [RefreshProperties(RefreshProperties.All)]        public Correct PercentStyle        {            get { return this.percentStyle; }            set { this.percentStyle = value; }        }        public PercentProgress()        {            InitializeComponent();            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);        }        protected override void WndProc(ref Message m)        {            base.WndProc(ref m); // 注意,这一句要先执行,否则看不到百分比。            switch (m.Msg)            {                case WM_PAINT:                    this.DrawPercent();                    break;            }        }        private void DrawPercent()        {            Graphics g = this.CreateGraphics();            float percent = (float)(((float)this.Value / (float)this.Maximum) * 100);            if (this.percentStyle == Correct.One)                this.text = string.Format("{0:F1}%", percent);            else this.text = string.Format("{0}%", (int)percent);            Rectangle rc = this.ClientRectangle;            SizeF size = g.MeasureString(this.text, this.font);            float x = ((float)rc.Width - size.Width) / 2+0.5f;            float y = ((float)rc.Height - size.Height) / 2+0.5f;            g.DrawString(this.text, this.TextFont, new SolidBrush(this.percentColor), new PointF(x, y));        }    }}

在PercentProgress.Designer.cs文件中:

namespace ControlLibrary{    partial class PercentProgress    {        /// <summary>        /// 必需的设计器变量。        /// </summary>        private System.ComponentModel.IContainer components = null;        /// <summary>        /// 清理所有正在使用的资源。        /// </summary>        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>        protected override void Dispose(bool disposing)        {            if (disposing && (components != null))            {                components.Dispose();            }            base.Dispose(disposing);        }        #region 组件设计器生成的代码        /// <summary>        /// 设计器支持所需的方法 - 不要        /// 使用代码编辑器修改此方法的内容。        /// </summary>        private void InitializeComponent()        {            this.SuspendLayout();            //             // PercentProgress            //             this.Size = new System.Drawing.Size(401, 73);            this.ResumeLayout(false);        }        #endregion    }}

接着给出运行效果示意图:

 

其实,这个方法还是有一个缺点,就是绘制出来的百分比有些许闪烁,希望有达人可以解决这个问题。同时如果代码有什么问题,欢迎指出。