Gradient Panel shows red cross when minimized and then restored

前端 未结 3 1272
感情败类
感情败类 2021-01-16 06:14

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

相关标签:
3条回答
  • 2021-01-16 06:39

    I would avoid creating a new LinearGradientBrush in the OnPaintBackground 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:

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

    Add function:

    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();
    }
    
    0 讨论(0)
  • 2021-01-16 06:57

    It doesn't look like you are disposing of the Brush correctly.

    Refactored code:

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

    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 the DoubleBuffered=True property as well to control flickering.

    I placed your Gradient brush in a Using() block so that it will get disposed.

    0 讨论(0)
  • 2021-01-16 07:02

    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 type System.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:

      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);
         }
      }
    
    0 讨论(0)
提交回复
热议问题