【问题标题】:C# LinearGradientBrush glitch when minimizing screen最小化屏幕时的 C# LinearGradientBrush 故障
【发布时间】:2016-11-08 18:43:12
【问题描述】:

我有以下代码在我的 winform 上创建混合背景:

public partial class Aging : Form
{
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        using (var brush = new LinearGradientBrush(this.ClientRectangle,
        Color.Transparent, Color.Transparent, LinearGradientMode.Vertical))
        {
            var blend = new ColorBlend();
            blend.Positions = new[] { 0, 3 / 10f, 1 };
            blend.Colors = new[] { Color.WhiteSmoke, Color.LightSteelBlue, Color.LightSteelBlue };
            brush.InterpolationColors = blend;
            e.Graphics.FillRectangle(brush, this.ClientRectangle);
        }
    }

结果是颜色背景从 LightSteelBlue 渐变为 WhiteSmoke:

问题是,如果我最小化屏幕,然后再最大化,应用程序将不再显示背景:

这是我收到的异常消息:

System.ArgumentException: Rectangle '{X=0,Y=0,Width=0,Height=0}' cannot have a width or height equal to 0.
at System.Drawing.Drawing2D.LinearGradientBrush..ctor(Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode)
at AgingStatusDb.Aging.OnPaintBackground(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,  
IntPtr wparam, IntPtr lparam)

我不是那么精明,也无法找出故障的根源。任何帮助将不胜感激。

【问题讨论】:

  • 最小化时可能已经发生。最好在开始时添加宽度> 0 的检查.. 虽然不能在这里重现。但是错误提到了Rectangle rect,而不是在您的代码中!?!
  • 嗯,它确实显示了背景,但它现在是失败的红十字会。并且将保持这种状态,一旦您的绘画代码崩溃,它将不会尝试再次运行它以避免异常风暴。您收到的异常消息非常好,您无法创建 0x0 像素的画笔。这很容易检查您的 OnPaintBackground() 方法,如果 CllientRectangle.Width 或 Height 为 0,则不执行任何操作。
  • 仅检查零宽度或高度是不够的。您还应该在构造函数中设置this.DoubleBuffered = true;。此外,您还需要设置this.SetStyle(ControlStyles.ResizeRedraw, true); 以在调整表单大小时重绘表单。

标签: c# .net winforms gdi+


【解决方案1】:

要解决异常,只需按照异常消息所说的:

矩形 '{X=0,Y=0,Width=0,Height=0}' 不能有宽度或高度 等于 0。

所以你可以简单地检查 ClientRectangle.Width==0ClientRectangle.Height==0 然后什么都不做,然后返回。

但修复错误后,最小化和还原后会有黑色背景。

如果要绘制表单的背景,上面的代码需要一些更正:

  • 您需要将控件设置为在调整大小时重绘自身。为此,您应该在构造函数中设置this.SetStyle(ControlStyles.ResizeRedraw, true);

  • 您需要启用双缓冲以防止闪烁。所以在构造函数集this.DoubleBuffered = true;

代码

public Form1()
{
    InitializeComponent();
    this.DoubleBuffered = true;
    this.SetStyle(ControlStyles.ResizeRedraw, true);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
    if (ClientRectangle.Width == 0 || ClientRectangle.Height == 0) return;
    using (var brush = new LinearGradientBrush(this.ClientRectangle,
        Color.Transparent, Color.Transparent, LinearGradientMode.Vertical))
    {
        var b = new ColorBlend();
        b.Positions = new[] { 0, 3 / 10f, 1 };
        b.Colors = new[] { Color.WhiteSmoke, Color.LightSteelBlue, Color.LightSteelBlue };
        brush.InterpolationColors = b;
        e.Graphics.FillRectangle(brush, this.ClientRectangle);
    }
}

【讨论】:

  • 很好的解决方案,我在试图解决它的路上走得很远。谢谢!
【解决方案2】:

有一种最简单的方法来做淡化背景。

在图形编辑器中或使用您的代码创建带有渐变的图像,但保存它:

protected override void OnLoad(EventArgs e)
{
    using (var brush = new LinearGradientBrush(this.ClientRectangle,
        Color.Transparent, Color.Transparent, LinearGradientMode.Vertical))
    {
        var blend = new ColorBlend();
        blend.Positions = new[] { 0, 3 / 10f, 1 };
        blend.Colors = new[] { Color.WhiteSmoke, Color.LightSteelBlue, Color.LightSteelBlue };
        brush.InterpolationColors = blend;

        using (var bmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height))
        {
            var g = Graphics.FromImage(bmp);
            g.FillRectangle(brush, ClientRectangle);
            bmp.Save("background.png", ImageFormat.Png);
        }
    }
}

运行并关闭应用程序。然后删除该代码。

最后设置上一步创建的表单背景图片:

this.DoubleBuffered = true;
this.BackgroundImageLayout = ImageLayout.Stretch;
this.BackgroundImage = new Bitmap("background.png");

【讨论】:

  • 感谢亚历山大的回答。第一个答案效果更好,因为我的项目需要动态背景。不幸的是,设置的 bmp 图像功能不足以满足我的需要。
猜你喜欢
  • 2014-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
  • 2011-10-27
  • 2020-03-24
  • 1970-01-01
相关资源
最近更新 更多