I have no idea why this is happening, but I created the below code which is a gradient panel, the panel is then docked to the left of the screen.
When the form is re-sized it displays correctly, however if you minimize the form and then restore it you get a big red X instead of the gradient.
Can anyone spot the error?
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();
}
}
It doesn't look like you are disposing of the Brush correctly.
Refactored code:
You don't have to invalidate on every Resize or SizeChanged because you already have the control set with the
ResizeRedraw=True
property. I added theDoubleBuffered=True
property as well to control flickering.I placed your Gradient brush in a
Using()
block so that it will get disposed.I would avoid creating a new
LinearGradientBrush
in theOnPaintBackground
handler.My guess is you could be hitting your GDI object limit (which you can check in task manager) as I don't think you are disposing your brushes correctly.
Move this to the constructor, or in a function that is called when the colours and styles properties change (and dispose of the previous before creating the new one)
Here is an example of what you can do while still allowing the properties to change the colours etc...
Edit properties:
Add function:
I'm doing something similar, but even cleaning up the
LinearGradientBrush
didn't fix it for me. Looking at the console output, I noticed "A first chance exception of typeSystem.ArgumentException
occurred in System.Drawing.dll." I believe this is because the ClientRectangle is 0,0 when the component is minimized. Adding this code seemed to fix it for me: