65.9K
CodeProject 正在变化。 阅读更多。
Home

将您的状态栏变成进度条(ProgressStatusStrip)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (11投票s)

2011年7月15日

CPOL

4分钟阅读

viewsIcon

44039

downloadIcon

1519

如何让你的状态栏变成进度条 (ProgressStatusStrip)。

ProgressStatusStrip.GIF

引言

在本文中,我将展示如何创建一个状态栏控件,使其充当你的进度条,同时保留 Windows 窗体的所有现有功能。

我第一次尝试这样做是重写 ToolStatusStripLabel 控件,这很成功,但有一些缺陷;首先,在加载窗体时,你必须手动调整 ToolStatusStripLabel 的大小,使其与状态栏的大小匹配,如果你想让它覆盖整个窗体的宽度。其次,如果你想在状态栏上放置多个标签(或其他控件),这将限制进度条的大小。

然后,我研究了重写状态栏控件,结果发现它实际上比我最初想象的要容易。 这使我可以拥有一个覆盖整个状态栏的进度条,并添加多个控件。

我还使用渐进颜色绘制的进度条,使用两种颜色和一个 LinearGradientBrush。你可以替换这部分代码来实现你自己的进度条绘制风格,或者使用 CodeProject 上找到的其他进度条示例。

使用代码

代码非常简单。 你首先需要创建一个新的控件类,该类基于标准 StatusStrip 控件。 我们不想重新发明轮子,而只对增强现有控件感兴趣,所以这是一个很好的基类。

public class ProgressStatusStrip : StatusStrip
{
}

接下来,我们添加一些新的局部变量,这些变量用于控件的增强。两个变量用于存储进度条的颜色,三个变量用于存储进度条的状态。 注意:你会注意到我使用 FLOAT 类型,主要原因是世界不是完整的,你很少需要完成一个漂亮的整数任务,因此你的进度增量通常是一个浮点数(例如,6 个任务,100/6 = 16.66…67)。 由于标准进度条使用 INT 作为 Value 属性,因此在递增进度时会丢失精度(除非你在代码中保留一个单独的变量来表示进度,并在每次迭代中将其分配给进度条)。 因此,通过使用 FLOAT,它可以减轻你的主代码的负担,以保持对其进度的准确跟踪。

#region ProgressStatusStrip Definitions 
private Color _barColor = Color.ForestGreen;
private Color _barShade = Color.LightGreen;

private float _progressMin = 0.0F;
private float _progressMax = 100.0F;
private float _progressVal = 0.0F;
#endregion

接下来,我们添加公开给用户的公共属性,允许他们在设计时和运行时配置类的进度条部分。 为每个属性添加描述并对其进行分类总是很不错的,这样它们就不会与其他控件属性混淆。 我们有五个属性,两个控制进度条的颜色,三个控制进度条的状态(这些与标准进度条的属性相匹配)。 注意:最好在用户更改属性值时进行一些数据验证,以确保你在其他地方没有任何代码问题,因此需要检查 Set 函数内部。

#region ProgressStatusStrip Properties
[Description("The color of the Progress Bar"), 
 Category("Progress Bar"), 
 DefaultValue(typeof(Color), "Color.ForestGreen")]
public Color ProgressColor
{
  get { return _barColor; }
  set { _barColor = value; this.Invalidate(); }
}

[Description("The shade color of the Progress Bar"), 
 Category("Progress Bar"), 
 DefaultValue(typeof(Color), "Color.LightGreen")]
public Color ProgressShade
{
  get { return _barShade; }
  set { _barShade = value; this.Invalidate(); }
}

[Description("The lower bound of the range the Progress Bar is working with"), 
 Category("Progress Bar"), DefaultValue(0.0F)]
public float Minimum
{
  get { return _progressMin; }
  set
  {
   _progressMin = value;
   if (_progressMin > _progressMax) _progressMax = _progressMin;
   if (_progressMin > _progressVal) _progressVal = _progressMin;
   this.Invalidate();
  }
}

[Description("The upper bound of the range the Progress Bar is working with"), 
 Category("Progress Bar"), DefaultValue(100.0F)]
public float Maximum
{
  get { return _progressMax; }
  set
  {
   _progressMax = value;
   if (_progressMax < _progressMin) _progressMin = _progressMax;
   if (_progressMax < _progressVal) _progressVal = _progressMax;
   this.Invalidate();
  }
}

[Description("The current value for the Progress Bar, " + 
             "in the range specified by the minimum and maximum properties"), 
 Category("Progress Bar"), DefaultValue(0.0F)]
public float Value
{
  get { return _progressVal; }
  set
  {
   _progressVal = value;
   if (_progressVal < _progressMin) _progressVal = _progressMin;
   if (_progressVal > _progressMax) _progressVal = _progressMax;
   this.Invalidate();
  }
}
#endregion

最后阶段是重写 OnPaint 方法; 这是我们处理进度条实际绘制的地方。 我们将实际进度计算为百分比; 如果我们没有取得任何进展,那么我们无事可做,只需调用基类的 OnPaint 方法,该方法处理标准状态栏部分的绘制。 如果我们取得了一些进展,我们需要绘制进度条,我们获取状态栏的可见边界,并调整此矩形的宽度以匹配我们需要显示的进度量。 现在我们创建一个带有选定颜色的 LinearGradientBrush,然后用此画笔绘制进度区域。

#region ProgressStatusStrip Methods
public ProgressStatusStrip() { }
 
protected override void OnPaint(PaintEventArgs pe)
{
  float progPercent = (float)(_progressVal / (_progressMax - _progressMin));
  if (progPercent > 0)
  {
   RectangleF progRectangle = pe.Graphics.VisibleClipBounds;
   progRectangle.Width *= progPercent;
   LinearGradientBrush progBrush = new LinearGradientBrush(
     progRectangle, _barColor, _barShade, LinearGradientMode.Horizontal);
   pe.Graphics.FillRectangle(progBrush, progRectangle);
   progBrush.Dispose();
  }

  base.OnPaint(pe);
}
#endregion

工作原理

编译此代码后,你将能够从工具箱中选择新控件以添加到任何窗体。 然后只需调整进度条属性并从任务更新 ProgressStatusStripValue 属性。

ProgressStatusStrip-Toolbox.jpg ProgressStatusStrip-Properties.jpg

重要提示!

你必须记住的最重要的事情是,添加到 ProgressStatusStrip 的任何控件**必须**将其 BackColor 设置为 Transparent; 否则,它们会部分阻止进度条被看到(如示例代码演示中所示)。

历史

  • 2011-07-14 - v1.0 - 添加文章。
  • 2011-07-15 - v1.1 - 更新文章,详细说明代码的工作原理。
© . All rights reserved.