Question

I have a custom panel designed to be able to either show a solid background color, a gradient background color, or a picture.

I've overridden both the BackgroundImage property and the OnPaint method like so:

protected override void OnPaint(PaintEventArgs pe){
    Rectangle rc = new Rectangle(0, 0, this.Width, this.Height);
    if (this.DrawStyle != DrawStyle.Picture){
        base.BackgroundImage = null;

            if (this.DrawStyle == DrawStyle.Solid){
                using (SolidBrush brush = new SolidBrush(this.PrimaryColor))
                    pe.Graphics.FillRectangle(brush, rc);
            }
            else if (this.DrawStyle == DrawStyle.Gradient){
                using (LinearGradientBrush brush = 
                       new LinearGradientBrush(
                           rc, this.PrimaryColor, this.SecondaryColor, this.Angle))
                pe.Graphics.FillRectangle(brush, rc);
            }
        }
    else if (this._BGImage != null)
        base.BackgroundImage = this._BGImage;
}

public override Image BackgroundImage{
    get { return this._BGImage; }
    set { this._BGImage = value; }
}

The reason being is that the control must be flexible enough to change the background type (Solid, Gradient or Picture) during run time, so the control holds onto the set background image and presents it when necessary.

I am running into a problem, however.

If I do not set the background image, there is no problem. OnPaint is called about 5 times and then it goes fine.

However, when I DO set the background image, it seems to go crazy, calling OnPaint over and over and over and over and over and over again.

This clearly has something to do with overriding the background image and it's a problem, because it's hanging up and nothing on the panel is getting updated until I change the panel appearance.

So I guess the question I have is why is it getting stuck in this OnPaint loop when I set the background image?

Was it helpful?

Solution

Comment out this:

// base.BackgroundImage = this._BGImage;

It's causing it to recursively paint itself. You should never set properties in a paint routine.

Furthermore, you aren't accomplishing anything by overriding the BackgroundImage, and if you do override the property, that should be the only place where you assign the base.BackgroundImage value. Consider removing that.

I reworked your code to this:

protected override void OnPaintBackground(PaintEventArgs e) {
  if (this.DrawStyle == DrawStyle.Picture) {
     base.OnPaintBackground(e);
  }
}

protected override void OnPaint(PaintEventArgs e) {
  Rectangle rc = this.ClientRectangle;
  if (this.DrawStyle == DrawStyle.Solid) {
    using (SolidBrush brush = new SolidBrush(this.PrimaryColor))
      e.Graphics.FillRectangle(brush, rc);
  } else if (this.DrawStyle == DrawStyle.Gradient) {
    using (LinearGradientBrush brush =
           new LinearGradientBrush(
               rc, this.PrimaryColor, this.SecondaryColor, this.Angle))
      e.Graphics.FillRectangle(brush, rc);
  }
  base.OnPaint(e);
}

Make sure to add this.DoubleBuffered = true; and this.ResizeRedraw = true; in your panel's constructor to avoid unnecessary flicker.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top