从System.Windows.Forms.ProgressBar派生的类不会覆盖OnPaint

时间:2013-06-18 07:19:49

标签: c# progress-bar onpaint

我创建了一个派生自System.Windows.Forms.ProgressBar的类。我按照MSDN建议的方法:

  • 将usercontrol添加到项目中
  • 打开用户控件的代码
  • 不是从System.Windows.Forms.UserControl派生,而是从ProgressBar派生。

此外,我重写了OnPaint,所以我可以自己绘画:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    // etc, do your own painting.

然而这个功能从未被调用过。断点不会在这里破裂。进度条正常绘制。我错过了什么?

1 个答案:

答案 0 :(得分:2)

遵循的程序正如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的派生类。这使得代码更小。此外,您还拥有Progressbar的所有功能。

此进度条没有条形的纯色,而是两种颜色之间的渐变色。它可以像任何其他控件一样使用工具箱添加。可以更改属性,就像更改进度条的属性一样。在属性窗口的底部,您将看到额外的属性。

创建它:

  • 创建项目
  • 在Solution Exploser - 添加 - 用户控件中,为其命名,例如ColorProgressBar
  • 在编辑器中打开ColorProgressBar的代码
  • 将基类从UserControl更改为System.Windows.Forms.ProgressBar
  • 根据您的需要更改课程,请参阅下面的示例

最重要的功能是OnPaint,它将改变ProgressBar的外观。其余的很简单:

  • 添加两个属性来描述渐变颜色
  • 在构造函数中,如上所述SetStyle以确保调用OnPaint:

    public partial class ColorProgressBar:System.Windows.Forms.ProgressBar {     public Color BarColorOutside {get;组; }     public Color BarColorCenter {get;组; }

    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。填充的Progressbar部分将填充渐变颜色。为此,我们需要知道进度条的填充宽度和高度。我们可以制作两个矩形:一个填充上半部分,另一个填充下半部分。填充将使用渐变画笔完成:从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);
        }
    }
}