繁体   English   中英

如何摆脱Visual Studio设计器抛出的“Out of memory”异常?

[英]How can I get rid of “Out of memory” exception thrown from Visual Studio designer?

请考虑以下代码:

主表单模板模型:

public partial class CustomForm : Form
{
    public CustomForm()
    {
        InitializeComponent();
        DoubleBuffered = true;
    }
}

具体表格模板型号:

public partial class PopupForm : CustomForm
{
    public PopupForm()
    {
        InitializeComponent();
        BTN_Maximize.Hide();
    }
}

派生形式:

public partial class SiteAccess : CustomForm
{
    public SiteAccess()
    {
        InitializeComponent();
        this.SizeGripStyle = SizeGripStyle.Show;
    }
}

(主要形式)

+

public partial class Edition : PopupForm
{
    public Edition()
    {
        InitializeComponent();
    }
}

+

public partial class Preferences : PopupForm
{
    public Preferences()
    {
        InitializeComponent();
    }
}

+

public partial class About : PopupForm
{
    public About()
    {
        InitializeComponent();
    }
}

在我的表单模板模型PopupForm中,我为一个空面板定义了一个Paint事件处理程序,如下所示:

private void PNL_TitleBar_Paint(object sender, PaintEventArgs e)
{
    Brush gradientBrush = new LinearGradientBrush(new Point(0, 0), 
                          new Point((int)e.ClipRectangle.Right, 0), 
                          Color.Gray, 
                          Color.FromArgb(255, 50, 50, 50));

    Pen gradientPen = new Pen(gradientBrush);

    e.Graphics.DrawLine(gradientPen, 
                        new Point((int)e.ClipRectangle.Left,  (int)e.ClipRectangle.Bottom - 1),
                        new Point((int)e.ClipRectangle.Right, (int)e.ClipRectangle.Bottom - 1));

    gradientPen.Dispose();
    gradientBrush.Dispose();
}

要简化它,只需在面板底部绘制一条渐变线。

问题来自于每当我尝试从PopupForm (版本,首选项或关于)的派生形式之一插入工具箱中的新控件时,我收到以下消息:

OutOfMemoryException异常

我之前向你展示了Paint事件处理程序的原因是因为我发现它是问题的根源,但我仍然不知道如何修复它。 实际上,如果我删除了Paint事件处理程序的代码,则根本不会抛出任何异常。

顺便说一下,我必须指定一些东西:

  1. 仅从Visual Studio Designer视图抛出异常(在编译之后)。
  2. 程序本身运行得非常好(完全没有例外)。
  3. 如果我执行程序,关闭它并返回到Designer,在窗体中插入控件时不会抛出任何异常。
  4. 但是,如果我重新构建解决方案(不执行程序)并返回到Designer,则在窗体中插入控件时将显示异常。

    • 我尝试使用'using'语句而不是直接调用Dispose()函数,但仍然没有。 另外,请记住,我在SiteAccess表单中的另一个Paint事件处理程序中有一个非常相似的代码,所以我真的怀疑这段代码是真正的问题。

有关这种奇怪行为的任何想法?

这是由代码中的错误引起的。 底层异常是LinearGradientBrush构造函数抛出的GDI +异常。 由于难以解释而臭名昭着,当它在设计时发生时会变得更糟。 从技术上讲,这在运行时也可能出错,只是不太可能。 您可以通过对代码进行少量更改来一致地重新调整它:

        Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
                  new Point((int)0, 0),            // <=== here
                  Color.Gray,
                  Color.FromArgb(255, 50, 50, 50));

KABOOM。 使用e.ClipRectangle来初始化画笔永远是正确的,你得到的渐变是高度不可预测的。 e.ClipRectangle值的变化取决于窗口的哪个部分需要重新绘制,现在你完全依赖它作为整个窗口。 例如,当您将窗口拖离屏幕边缘时,情况并非如此。 视觉神器应该非常明显。

固定:

        Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
                  new Point(this.ClientSize.Width, 0),
                  Color.Gray,
                  Color.FromArgb(255, 50, 50, 50));

必须修复DrawLine()调用以使线条出现在一致的位置。 不要担心剪辑,Windows已经自动处理它。

外卖是要非常小心使用e.ClipRectangle属性,它经常偶然工作,但几乎不是你真正想要使用的。 只能用它来检查是否可以跳过绘图部件,因为它们位于裁剪区域之外。 哪些代码很难获得回报,在启用Aero的现代Windows版本中不会经常发生。 不要打扰。

Paint处理程序中,您可以检查DesignMode属性并在Forms Designer中跳过绘制标题栏:

    void PNL_TitleBar_Paint(object sender, PaintEventArgs e)
    {
        if (DesignMode)
            return;
        using (Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
                              new Point((int)e.ClipRectangle.Right, 0),
                              Color.Gray,
                              Color.FromArgb(255, 50, 50, 50)))
        using (Pen gradientPen = new Pen(gradientBrush))
        {

            e.Graphics.DrawLine(gradientPen,
                                new Point((int)e.ClipRectangle.Left, (int)e.ClipRectangle.Bottom - 1),
                                new Point((int)e.ClipRectangle.Right, (int)e.ClipRectangle.Bottom - 1));
        }
    }

这将适用于您的Paint方法和大多数其他情况。 有关异常情况的讨论,例如在构造函数中要做什么,请参阅此处

(建议还using语句替换对Dispose显式调用。)

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM