0

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

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

此外,我重写了 OnPaint,因此我可以自己绘制它:

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

然而这个函数永远不会被调用。断点不会在这里中断。进度条正常绘制。我错过了什么?

4

1 回答 1

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 的派生类。这使得代码更小。此外,您还拥有进度条的所有功能。

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

创建它:

  • 创建您的项目
  • 在解决方案资源管理器 - 添加 - 用户控件中,为其命名,例如 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);
        }
    }
}
于 2013-06-18T07:19:48.610 回答