渐变面板在最小化时显示红叉,然后恢复

时间:2012-02-21 12:07:23

标签: c# winforms drawing panel gradient

我不知道为什么会这样,但我创建了下面的代码,这是一个渐变面板,然后面板停靠在屏幕左侧。

当窗体重新调整大小时,它会正确显示,但是如果你最小化窗体然后恢复它,你会得到一个大的红色X而不是渐变。

有人能发现错误吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;

public class GradientPanel : Panel
{
    private Color ColorA = Color.LightBlue;
    private Color ColorB = Color.Red;
    private LinearGradientMode GradientFillStyle = LinearGradientMode.ForwardDiagonal;
    private Brush gradientBrush;

    public Color colourStart
    {
        get { return ColorA; }
        set { ColorA = value; Invalidate(); }
    }
    public Color colourEnd
    {
        get { return ColorB; }
        set { ColorB = value; Invalidate(); }
    }
    public LinearGradientMode colourGradientStyle
    {
        get { return GradientFillStyle; }
        set { GradientFillStyle = value; Invalidate(); }
    }

    public GradientPanel()
    {
        handlerGradientChanged = new EventHandler(GradientChanged);
        ResizeRedraw = true;        
    }

    private EventHandler handlerGradientChanged;

    protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
    {
        gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle);

        e.Graphics.FillRectangle(gradientBrush, ClientRectangle);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (gradientBrush != null) gradientBrush.Dispose();
        }
        base.Dispose(disposing);
    }

    protected override void OnResize(EventArgs eventargs)
    {
        Invalidate();
        //base.OnResize(eventargs);
    }
    protected override void OnSizeChanged(EventArgs e)
    {
        Invalidate();
        //base.OnSizeChanged(e);
    }
    private void GradientChanged(object sender, EventArgs e)
    {
        if (gradientBrush != null) gradientBrush.Dispose();
        gradientBrush = null;
        Invalidate();
    }

}

3 个答案:

答案 0 :(得分:4)

我正在做类似的事情,但即使清理LinearGradientBrush也无法解决这个问题。查看控制台输出,我注意到“System.Drawing.dll中出现了System.ArgumentException类型的第一次机会异常。”我相信这是因为当组件最小化时,ClientRectangle为0,0。添加此代码似乎为我解决了这个问题:

  protected override void OnPaintBackground(PaintEventArgs e)
  {
     base.OnPaintBackground(e);
     if (this.gradientBrush != null)
        this.gradientBrush.Dispose();
     if (this.ClientRectangle.Width > 0 && this.ClientRectangle.Height > 0)
     {
        this.gradientBrush = new LinearGradientBrush(this.ClientRectangle,
           FROM_GRADIENT_COLOR, TO_GRADIENT_COLOR, LinearGradientMode.Horizontal);

        e.Graphics.FillRectangle(this.gradientBrush, this.ClientRectangle);
     }
  }

答案 1 :(得分:2)

我会避免在LinearGradientBrush处理程序中创建新的OnPaintBackground

我的猜测是你可能会达到你的GDI对象限制(你可以在任务管理器中检查),因为我认为你没有正确处理你的刷子。

将其移动到构造函数,或者在颜色和样式属性更改时调用的函数(并在创建新属性之前处置之前)

以下是您可以执行的操作示例,同时仍允许属性更改颜色等...

编辑属性:

public Color colourStart
{
    get { return ColorA; }
    set { ColorA = value; RefershBrush(); }
}
public Color colourEnd
{
    get { return ColorB; }
    set { ColorB = value; RefershBrush(); }
}
public LinearGradientMode colourGradientStyle
{
    get { return GradientFillStyle; }
    set { GradientFillStyle = value; RefershBrush(); }
}

添加功能:

private void RefershBrush()
{
    //I think this IF block should work with no problems, been a while working with brush
    if(gradientBrush != null)
    {
        gradientBrush.Dispose();
    }

    gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle);
    Invalidate();
}

答案 2 :(得分:1)

看起来你没有正确处理画笔。

重构代码:

public class GradientPanel : Panel {
  private Color ColorA = Color.LightBlue;
  private Color ColorB = Color.Red;
  private LinearGradientMode GradientFillStyle = LinearGradientMode.ForwardDiagonal;

  public GradientPanel() {
    DoubleBuffered = true;
    ResizeRedraw = true;
  }

  public Color colourStart {
    get { return ColorA; }
    set { ColorA = value; Invalidate(); }
  }

  public Color colourEnd {
    get { return ColorB; }
    set { ColorB = value; Invalidate(); }
  }

  public LinearGradientMode colourGradientStyle {
    get { return GradientFillStyle; }
    set { GradientFillStyle = value; Invalidate(); }
  }

  protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) {
    using (var gradientBrush = new LinearGradientBrush(ClientRectangle, ColorA, ColorB, GradientFillStyle)) {
      e.Graphics.FillRectangle(gradientBrush, ClientRectangle);
    }
  }
}

您不必在每个Resize或SizeChanged上失效,因为您已经拥有具有ResizeRedraw=True属性的控件集。我还添加了DoubleBuffered=True属性来控制闪烁。

我将Gradient画笔放在Using()块中,以便它被处理掉。