[英]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.