6

我昨天从 VS 2010 切换到 VS 2012,除此之外一切似乎都很顺利。

我的表单上有一个按钮,按下时会扩展表单的宽度以显示其他控件。再次按下按钮,它会减小隐藏这些控件的宽度。现在所有这些在 VS 2010 中运行良好,并且在我在 VS 2012 中调试时也运行良好,但是一旦我发布或编译项目并在您单击按钮时打开 .exe 时,它​​会将宽度添加为 5 而不是100+ 它需要。我再次单击它,然后它会像它应该的那样将其更改为 372 并显示我的所有控件。我再次单击它以隐藏控件,它隐藏了部分控件(转到 188 + 神秘的 5)我希望所有这些都有意义,并希望有更好的方法来运行我需要的过程。

这是我目前正在使用的代码,在从 2010 年切换到 2012 年之间我没有进行任何更改。事实上,如果我在 2010 年打开相同的解决方案并发布一切正常。

    private void button1_Click(object sender, EventArgs e)
    {
        if (this.Width == 188)
        {
            this.Width = 372;
            this.Height = 540;
            progressBar.Value = 100;
            copied_status.Text = ("Output View Enabled");
        }
        else
        {
            progressBar.Value = 100;
            copied_status.Text = ("Output View Disabled");
            this.Width = 188;
            this.Height = 540;
        }

        if (this.Width == 372)
        {
            button1.Text = "<<";
        }
        else
            button1.Text = ">>";

    }
4

1 回答 1

12

您的表单宽度已经很久没有达到 188 像素了。现在有了 VS2012,Windows 终于不再撒谎了。

有争议的是 Aero 中的胖窗口边框。当在 Vista 中引入该功能时,它们是一个极端的 appcompat 问题。非常必要,因为这两个像素很难用鼠标击中。但与应用程序创建窗口的方式完全不兼容。它要求 CreateWindow() 函数的特定窗口大小、外部大小、nWidth 和 nHeight 参数。但真正重要的是客户区的大小,即边框内的窗口部分。如果 Microsoft 对此不采取任何措施,那么旧的应用程序最终会导致客户区太小。这看起来很糟糕,窗口内容不再适合。例如,表单底部或右侧的控件不会完全显示。

所以,偷偷摸摸地,Aero 使窗口变大了胖边框的额外宽度。当应用程序询问窗口大小时,它偷偷说它小了相同的添加宽度。该应用程序不知道比它仍然以与 XP 上相同的窗口大小运行更好。这工作得很好,但并不完全理想。例如,很难让窗口边缘与那个谎言正确对齐。

Aero 是否会谎报窗口大小取决于 EXE 标头中记录的目标操作系统。当它看到比 6.00 更早的版本,即 Vista 版本号时,它会假定您的 EXE 是一个不知道粗边框功能的遗留程序。所以需要被骗。您已经将目标版本号设置为 4.00 运行了很长时间,它是由 .NET 编译器在构建程序时编写的。你可以看到它dumpbin.exe /headers yourapp.exe

这最终在 VS2012 和 .NET 4.5 中改变了。这是一个在 XP 中不可用的 .NET 版本。编译器最终可以硬性假设 XP 已成为历史,并且您将在支持 Aero 的 Windows 版本上运行。因此它将 EXE 标头中的目标 Windows 版本设置为 6.00。相应地,Aero 现在将不再对窗口大小撒谎。你得到的是真正的,而不是假的。

因此,快速解决方法是将目标 .NET 框架版本更改为 4.0。这在 XP 上可用,所以你会再次被骗。

当然,最好修复您的代码。永远不要使用 Size、Width 或 Height 属性,它们将不可避免地取决于边框和标题的大小。请改用 ClientSize 属性,这是稳定的属性,也是您真正关心的属性。但也要小心该属性,当表单在其视频适配器设置为每英寸超过 96 个点的机器上运行时,它可能会重新缩放。在 Vista 及更高版本中非常易于访问的另一个功能。重新缩放会按 DPI 设置按比例更改 ClientSize。

真正的解决方法是使用 bool 字段来跟踪窗口状态。并根据要隐藏或显示的控件的位置设置 ClientSize 属性。大致如此:

private bool enlarged;

private void button1_Click(object sender, EventArgs e)
{
    enlarged = !enlarged;
    int width = someControl.Left - 5;
    if (enlarged) width = someControl.Right + 5;
    this.ClientSize = new Size(width, this.ClientSize.Height);
}

将此代码中的 someControl 替换为您的控件的名称。

于 2013-04-13T01:08:26.703 回答