1

首先,对不起我的英语,因为它不是我的母语。

问题发生在我的 .NET Windows Forms 应用程序中,并且由于某些原因仅在 Virtaul PC Windows 7 (x64) 上重现。

当调整包含许多自定义控件的主应用程序窗体的大小时,我在应用程序的一个地方遇到了 Win32Exception,包括两个相互堆叠的 tabcontrols 等。异常的消息是“创建窗口句柄时出错”。我花了一些时间在 Microsoft 支持网站上找到了该问题的解决方案。这与我的情况非常相似。来自网站的引用:

在 .NET 应用程序中,停靠控件有时在它们的父级嵌套时不会调整大小。在 64 位和 32 位平台上都会出现此问题,但在 32 位系统上需要更深的嵌套级别。

发生的情况是,当顶层控件布局时,SetBoundsCore 调用 SetWindowPos 来调整子控件的大小。每个子控件都会收到一个 WM_WINDOWPOSCHANGED 通知,该通知会触发一个布局事件,该事件调用 SetBoundsCore,该事件调用 SetWindowPos。对 SetWindowPos 的每次调用都会进入内核模式,然后退出以传递 WM_WINDOWPOSCHANGED 通知。最终线程耗尽内核堆栈空间,SetWindowPos 静默失败。

建议的解决方案是覆盖容器控件的 OnSizeChanged 方法(如 Panels 或 TabControl(在我的情况下)):

    protected override void OnSizeChanged(EventArgs e)
    {
        if (this.Handle != null)
        {
            BeginInvoke((MethodInvoker)(() => base.OnSizeChanged(e);));
        }
    }

我成功地将这个解决方案应用于我的案例:创建了自定义 TabControl(从普通的 winforms TabControl 类继承)并使用我的自定义控件实例更改了 TabControl 实例。问题消失了!但...

...当我在 CCnet 构建机器上启动 Build 时,我在不同的单元测试中遇到了很多 Win32Exception-s“创建窗口句柄时出错”,但最有趣的不是我有问题的控件(包含自定义 TabControl 对象)单元测试!错误情况不同,但它们与我的自定义控件无关。当我恢复更改时,一切正常,创建了构建(单元测试成功执行)。

应用更改修复了用户应用程序的可操作性,但在创建构建时导致单元测试失败,这让我完全感到困惑。

顺便说一句,在本地机器上,所有单元测试在任何情况下都可以正常执行(有或没有修复)。

我花了很多时间来调查这个问题,现在我只有一个假设:ccnet build machine 在一个进程中执行所有单元测试,并且测试没有正确处理测试数据(gdi 对象)(在拆卸时),因为错误“错误创建窗口句柄”通常发生在达到允许的 gdi 对象句柄 (10000) 的限制时。

能否请您分享您的专业意见?提前非常感谢。

4

3 回答 3

0

如果在 CCNET 机器上作为单元测试运行,它可能在非交互式服务上下文中运行,这可能会阻止创建窗口,因为没有人可以查看它们。

于 2012-05-08T15:35:25.317 回答
0

与您的错误没有直接关系,但访问 Handle 属性将强制创建窗口句柄,这有时是不可能的。不应像这样执行句柄检查:

if (this.Handle != null)

相反,检查 IsHandleCreated 属性:

if (this.IsHandleCreated)

不久前,我在有关此问题的博客文章中提到了这一点,但似乎没有被注意到。

于 2012-05-08T15:13:24.353 回答
0

我对深度嵌套的控件有同样的问题。但是,为了获得适当的解决方案,我不得不覆盖并延迟 SetBoundsCore

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        if (this.IsHandleCreated)
        {
            this.BeginInvoke(
                             (MethodInvoker)delegate
                             {
                                 base.SetBoundsCore(x, y, width, height, specified);
                             });
        }
    }
于 2015-11-19T12:01:27.970 回答