下面的过程与 MSDN 建议的完全一样。进度条具有 OnPaint 功能,因此根据 MSDN,您的 OnPaint 应该被调用。
不调用它的原因是因为您必须声明您将自己绘制控件。在旧的 MFC 中,这称为 OwnerDrawn。要告诉系统您想自己绘制控件,您必须更改控件的样式。这是使用 Control.SetStyle 完成的:
public partial class ColorProgressBar : System.Windows.Forms.ProgressBar
{
public ColorProgressBar()
{
InitializeComponent();
this.SetStyle(ControlStyles.UserPaint, true);
// etc, other initializations
}
这将注意您的 OnPaint 将被调用。
以完整的 ColorProgressBar 为例。这个类的代码可以在别处找到,但这里它被重写为 System.Windows.Forms.ProgressBar 的派生类。这使得代码更小。此外,您还拥有进度条的所有功能。
这个进度条没有纯色,而是两种颜色之间的渐变色。它可以像任何其他控件一样使用工具箱添加。可以像更改进度条的属性一样更改属性。在属性窗口的底部,您将看到额外的属性。
创建它:
- 创建您的项目
- 在解决方案资源管理器 - 添加 - 用户控件中,为其命名,例如 ColorProgressBar
- 在编辑器中打开 ColorProgressBar 的代码
- 将基类从 UserControl 更改为 System.Windows.Forms.ProgressBar
- 根据您的需要更改课程,请参见下面的示例
最重要的功能是 OnPaint,它将改变 ProgressBar 的外观。剩下的很简单:
- 添加两个属性来描述渐变颜色
在构造函数中,如上所述的 SetStyle 以确保调用 OnPaint:
公共部分类 ColorProgressBar : System.Windows.Forms.ProgressBar { public Color BarColorOutside { get; 放; } 公共颜色 BarColorCenter { 获取;放; }
public ColorProgressBar()
{
BarColorOutside = Color.Black;
BarColorCenter = Color.Yellow;
InitializeComponent();
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// your own painting will be added later
}
现在检查这个基础是否有效:
- 建造
- 创建一个表格。将进度条添加到表单
- 使用属性给进度条一个值和初始颜色
- 调试以检查您的 onPaint 是否被调用。
现在是onPaint。填充的进度条部分将填充渐变色。为此,我们需要知道进度条的填充宽度和高度。我们可以制作两个矩形:一个填充上半部分,一个填充下半部分。填充将使用渐变画笔完成:上半部分从 barColorOutside 到 barColorCenter,下半部分从 barColorCenter 到 barColorOutside。这样,中心颜色将位于进度条的中心。
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// the part that has to be filled with a colored progress:
int fillWidth = (Width * Value) / (Maximum - Minimum);
if (fillWidth == 0)
{ // nothing to fill
return;
}
// the two rectangles:
Rectangle topRect = new Rectangle(0, 0, fillWidth, Height / 2);
Rectangle bottomRect = new Rectangle(0, Height / 2, fillWidth, Height);
// Paint upper half: the gradient fills the complete topRect,
// from background color to foreground color
LinearGradientBrush brush = new LinearGradientBrush(topRect, BarColorOutside,
BarColorCenter, LinearGradientMode.Vertical);
e.Graphics.FillRectangle(brush, topRect);
brush.Dispose();
// paint lower half: gradient fills the complete bottomRect,
// from foreground color to background color
brush = new LinearGradientBrush(bottomRect, BarColorCenter, BarColorOutside,
LinearGradientMode.Vertical);
e.Graphics.FillRectangle(brush, bottomRect);
brush.Dispose();
// we have missed one line in the center: draw a line:
Pen pen = new Pen(BarColorCenter);
e.Graphics.DrawLine(pen, new Point(0, topRect.Bottom),
new Point(fillWidth, topRect.Bottom));
pen.Dispose();
// if style is blocks, draw vertical lines to simulate blocks
if (Style == ProgressBarStyle.Blocks)
{
int seperatorWidth = (int)(this.Height * 0.67);
int NrOfSeparators = (int)(fillWidth / seperatorWidth);
Color sepColor = ControlPaint.LightLight(BarColorCenter);
for (int i = 1; i <= NrOfSeparators; i++)
{
e.Graphics.DrawLine(new Pen(sepColor, 1),
seperatorWidth * i, 0, seperatorWidth * i, this.Height);
}
}
}