【问题标题】:Error creating window handle in an .NET MDI application在 .NET MDI 应用程序中创建窗口句柄时出错
【发布时间】:2011-04-21 09:44:22
【问题描述】:

我有一个带有选项卡控件的 MDI 应用程序。在某些机器上,打开新选项卡时出现“创建窗口句柄时出错”异常。这只发生在某些机器上,主要是慢速机器。 使用 .NET Framework 4.0。

过去几天我一直在调查这个问题,这让我发疯了!我在 MSDN 论坛上找到了以下内容 Hans Passant 的解决方案MSDN Forum 根据答案,它与处于最大化状态的活动 MDI 孩子有关。给定的解决方案是在显示新选项卡之前将活动子项设置为正常窗口状态,然后再将其恢复。此解决方案有效,但我真的不喜欢解决方法导致的闪烁。

堆栈跟踪如下:

创建窗口句柄时出错:

在 System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd,Int32 消息, 在 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) 在 System.Windows.Forms.Control.CreateHandle() 在 System.Windows.Forms.Form.CreateHandle() 在 System.Windows.Forms.Control.get_Handle() 在 System.Windows.Forms.Form.SetVisibleCore(布尔值) 在 System.Windows.Forms.Control.Show() 在 WinForms\Forms\Tabs\TabManager.cs 中的 Client.UI.WinForms.Controls.TabManager.OpenNewTab(BaseTab2 选项卡):第 82 行 在 WinForms\Forms\Tabs\TabManager.cs 中的 Client.UI.WinForms.Controls.TabManager.OpenTab(BaseTab2 选项卡):第 183 行 在 WinForms\Forms\MainForm.cs:line 4372 中的 Client.UI.WinForms.MainForm.buttonLicenses_Click(Object sender, EventArgs e)

代码:

    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);
        }
    }

更新:在Microsoft support找到这个
当以下两个条件都为真时,就会发生这种情况。

  1. MDI 子窗体包含一个作为其他控件父级的控件。
  2. MDI 子窗体上的父控件从 Layout 或 Resize 事件的事件处理程序中的 Controls 集合中删除一个子控件。

【问题讨论】:

  • 所以基本上,您正在寻找Hans 在MSDN 线程中提出的解决方案的替代?一种避免闪烁的?
  • 可以通过调用SuspendLayout/ResumeLayout避免闪烁吗?

标签: .net tabs window mdi


【解决方案1】:

Microsoft 支持文章与您找到的 MSDN 论坛帖子的情况相同。跟你的搭配不太好。使用 Taskmgr.exe 的“进程”选项卡进行诊断。查看 + 选择列并勾选句柄、用户对象和 GDI 对象。使用过程时请注意这些值。

可能的情况是您会看到 USER 对象的值无限制地攀升。 Windows 在达到 10000 时将其拉出,这对于一个进程来说是太多的窗口。

这是由于从代码中的父级中删除控件而不调用其 Dispose() 方法引起的。如果 Taskmgr.exe 无法帮助您找到它,请在您的代码中搜索“Controls.Remove”或“Controls.Clear”。也许您正在删除标签页。您删除的控件暂时重新设置为“停车窗口”。如果您不给他们另一个父母或不调用他们的 Dispose() 方法,他们将永远卡在那里。那是一个泄漏。炸弹的代码不是导致问题的代码。

【讨论】:

  • 当崩溃发生时,用户对象大约是 170,GDI 对象大约是 170,Hadels 大约是 350。如果您认为问题是因为我们达到了 .net 或 windows 支持的最大限制那么你能解释一下为什么这只发生在某些计算机上吗?它发生在内存/处理能力低的计算机上。谢谢
  • 好吧,那就从头开始吧。你无法摆脱重绘。如果您不断最大化 MDI 子项,则 MDI 不是正确的窗口模型。使用一个简单的表单来显示和处理多个用户控件之一。
  • 您在 MSDN 论坛上提出的解决方案/解决方法有效,所以我猜句柄不是问题。解决方法很好,除了“闪烁”。也许闪烁不是正确使用的词。发生的事情是 MDI 孩子从最大化状态到正常状态,然后又回到最大化状态——这个过程看起来一点也不好看。这就是我所说的“闪烁”
  • 呃,为什么会回到最大化?如果您不希望新的孩子最大化,那么只需从 MSDN 论坛帖子中的解决方法代码中删除最后一条语句。
  • MDI 已经经历了恢复 + 切换 + 最大化周期,即使没有你帮助它提前完成,这样错误就不会字节。是的,如果子窗体有很多控件,重绘(3 次)的数量是非常明显的。唯一的解决办法是使用更少的控件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 2019-11-19
  • 2011-10-17
  • 1970-01-01
  • 2013-12-10
相关资源
最近更新 更多