本篇文章教大家怎么重绘ProgressBar,效果图如下:
此控件功能比较单一,不用多少代码就可以实现。全部如下:
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自带进度条所没有的。我们需要达到一种效果就是当进度条到达显示百分比的位置时,在进度条上的百分比部分显示为白色,在进度条之外的百分比显示为黑色。如图:
难点在于一个字符就要一半显现白色,一半显示黑色。实现方法是,先把所有百分比用黑色画出来,然后在上面覆盖白色的一部分,白色的一部分需要先在内存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