簡體   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