2011-04-21 67 views
1

我有一個帶有選項卡控件的MDI應用程序。在某些機器上,當打開一個新選項卡時,出現「錯誤創建窗口句柄」異常。這隻發生在一些機器上,大多數是慢速機器。 使用.NET Framework 4.0。在.NET MDI應用程序中創建窗口句柄時出錯

我在過去的幾天裏一直在調查這個問題,它讓我瘋狂了!我在MSDN論壇上發現以下內容 Hans Passant在此MSDN Forum 的解決方案根據答案,它與處於最大化狀態的活動MDI子代有關。給出的解決方案是在顯示新選項卡之前將活動子窗口設置爲正常窗口狀態,然後再將其恢復。此解決方案的工作原理,但我真的不喜歡解決方法導致的閃爍。

堆棧跟蹤如下:

錯誤創建窗口句柄:

 
    at System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd, Int32 msg, 
    at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) 
    at System.Windows.Forms.Control.CreateHandle() 
    at System.Windows.Forms.Form.CreateHandle() 
    at System.Windows.Forms.Control.get_Handle() 
    at System.Windows.Forms.Form.SetVisibleCore(Boolean value) 
    at System.Windows.Forms.Control.Show() 
    at Client.UI.WinForms.Controls.TabManager.OpenNewTab(BaseTab2 tab) in WinForms\Forms\Tabs\TabManager.cs:line 82 
    at Client.UI.WinForms.Controls.TabManager.OpenTab(BaseTab2 tab) in WinForms\Forms\Tabs\TabManager.cs:line 183 
    at Client.UI.WinForms.MainForm.buttonLicenses_Click(Object sender, EventArgs e) in WinForms\Forms\MainForm.cs:line 4372 

代碼:

private void OpenNewTab(BaseTab2 tab) 
    { 
     tab.MdiParent = MainForm.Instance; 
     tab.WindowState = FormWindowState.Maximized; 
     tab.Show(); <----- [EXCEPTION THROWN HERE] 

     if (tab.Path != String.Empty) 
     { 
      RecentManager.Add(tab.Path); 
      RecentManager.SetOpen(tab.Path, true); 
     } 
    } 

UPDATE:發現這在Microsoft support
可以發生這種情況時,這兩個以下條件屬實。

  1. MDI子窗體包含父母其他控件的控件。
  2. MDI子窗體上的父控件從Layout或Resize事件的事件處理程序中的Controls集合中刪除子控件。
+0

所以基本上,你正在尋找一個*替代*解決方案漢斯建議在MSDN線程?一個避免閃爍? – 2011-04-21 11:07:18

+0

你可以通過調用SuspendLayout/ResumeLayout來避免閃爍? – 2016-07-29 01:24:11

回答

3

Microsoft支持文章與您找到的MSDN論壇帖子是相同的場景。這與你的不匹配。使用Taskmgr.exe,進程選項卡對此進行診斷。查看+選擇列並勾選句柄,USER對象和GDI對象。在使用過程中,請注意這些值。

可能的情況是,您會看到USER對象的值無限制地爬升。 Windows在達到10000時將地毯拉出,這是由一個進程創建的太多窗口。

這是由於在不調用其Dispose()方法的情況下從代碼中的父代中移除控件而導致的。如果Taskmgr.exe無法幫助您找到它,請在代碼中搜索「Controls.Remove」或「Controls.Clear」。也許你正在刪除一個標籤頁。您刪除的控件暫時重新添加到「停車窗口」。如果你不給他們另一個父母或者不要調用他們的Dispose()方法,他們會永遠卡在那裏。這是一個泄漏。炸彈的代碼不是導致問題的代碼。

+0

發生崩潰時,用戶對象約爲170,GDI對象約爲170,Hadels約爲350. 如果您認爲問題是由於我們達到.net或windows支持的最大限制而引起的,那麼請您解釋一下爲什麼只在某些電腦上發生這種情況? 它發生在計算機上具有低內存/處理能力。 謝謝 – Magnus 2011-04-21 12:01:10

+0

那麼,從頭開始。你無法擺脫重繪。如果你經常最大化一個MDI孩子,那麼MDI不是正確的開窗模型。使用一個簡單的表單來顯示和處理幾個用戶控件中的一個。 – 2011-04-21 12:04:27

+0

您在MSDN論壇上提出的解決方案/解決方法可行,所以Handles不能成爲我猜測的問題。 解決方法很好,除了「閃爍」。也許閃爍不是正確的詞使用。發生的事情是,MDI孩子從最大化狀態變爲正常狀態,再次回到最大化狀態 - 而且這個過程看起來並不好。這就是我所說的「閃爍」 – Magnus 2011-04-21 12:38:33