简体   繁体   English

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

[英]Gradient Panel shows red cross when minimized and then restored

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. 调整表单大小后,它可以正确显示,但是,如果最小化表单然后将其还原,则会得到一个大的红色X而不是渐变。

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

}

I'm doing something similar, but even cleaning up the LinearGradientBrush didn't fix it for me. 我正在做类似的事情,但是即使清理LinearGradientBrush也无法解决它。 Looking at the console output, I noticed "A first chance exception of type System.ArgumentException occurred in System.Drawing.dll." 查看控制台输出时,我注意到“ System.ArgumentException类型的第一次机会异常发生在System.Drawing.dll中。” I believe this is because the ClientRectangle is 0,0 when the component is minimized. 我相信这是因为最小化组件时ClientRectangle为0,0。 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);
     }
  }

I would avoid creating a new LinearGradientBrush in the OnPaintBackground handler. 我会避免在OnPaintBackground处理程序中创建新的LinearGradientBrush

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. 我的猜测是您可能达到了GDI对象限制(可以在任务管理器中检查),因为我认为您没有正确设置画笔。

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) 将其移到构造函数中,或在color和styles属性更改时调用的函数中(并在创建新函数之前将其丢弃)

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

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. 您不必使每个Resize或SizeChanged都失效,因为您已经设置了带有ResizeRedraw=True属性的控件。 I added the DoubleBuffered=True property as well to control flickering. 我还添加了DoubleBuffered=True属性来控制闪烁。

I placed your Gradient brush in a Using() block so that it will get disposed. 我将您的“渐变”笔刷放置在Using()块中,以便对其进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 未最小化时仍显示弹出窗口 - Popup still shows when not minimized 窗口最小化后不恢复 - Window is not restored after minimized WebBrowser对象的内容在最小化表单然后恢复时会更改位置 - WebBrowser object content changes position when form is minimized and then restored 状态栏大红叉出现 - statusbar big red cross shows up WPF 最小化拥有的窗口应该保持最小化,如果 Parent 被最小化然后恢复 - WPF minimized owned windows should stay minimized, if Parent is minimized and then restored 更改选项卡选择时,除非最小化,最大化或恢复widnow屏幕,否则不会重绘子面板 - When changing tab selections, child panels are not redrawn unless widnow screen is minimized, maximized or restored asp.net 浏览器页面最小化/向下恢复时的页面调整 state - asp.net page adjustment when browser page is minimized/restored down state 为什么 VS 2019 中的文件夹显示红叉“X”? - Why folders in VS 2019 shows red cross 'X'? 从最小化状态还原后,如何重新绘制表单? - How do I repaint a form after it was restored from a minimized state? 具有未绑定DataTable网格的DataGridView在最小化和还原之前不会显示更新的数据 - DataGridView with unbound DataTable grid not showing updated data until minimized and restored
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM