Градиентная панель показывает красный крест, когда свернут, а затем восстановлен - PullRequest
1 голос
/ 21 февраля 2012

Понятия не имею, почему это происходит, но я создал приведенный ниже код, который представляет собой панель градиента, затем панель закрепляется слева от экрана.

Когда форма масштабируетсяотображается правильно, однако, если вы минимизируете форму и затем восстановите ее, вместо градиента вы получите большой красный крестик *.

Кто-нибудь может обнаружить ошибку?

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 ]

4 голосов
/ 18 октября 2012

Я делаю нечто подобное, но даже очистка LinearGradientBrush не исправила это для меня.Глядя на вывод консоли, я заметил «Первое случайное исключение типа System.ArgumentException произошло в System.Drawing.dll».Я считаю, что это потому, что 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);
     }
  }
2 голосов
/ 21 февраля 2012

Я бы не стал создавать новый 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();
}
1 голос
/ 21 февраля 2012

Не похоже, что вы правильно утилизируете кисть.

Рефакторированный код:

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);
    }
  }
}

Вам не нужно делать недействительными при каждом изменении размера или SizeChanged, потому что вы ужеустановите элемент управления со свойством ResizeRedraw=True.Я также добавил свойство DoubleBuffered=True для управления мерцанием.

Я поместил вашу кисть градиента в блок Using() так, чтобы он был ликвидирован.

...