这很奇怪。我移植了一个在VS2008下可以正常工作的项目,但是当我使用VS2017进行构建时,一行的存在会导致我的对话框调整大小-该代码甚至不需要运行,它只需要存在于执行该操作的子例程中即可。跑!
我已经创建了该程序的最简单版本,以展示这种行为。尝试在不同版本的Visual Studio下构建/运行。
我既希望解释为什么会发生这种情况,也希望能解决它。谢谢。

using System;
using System.IO;
using System.Windows.Forms;
using System.Windows.Media.Imaging; // Need reference to PresentationCore

namespace Test2017
{
    public class MainDlg : Form
    {
        [STAThread]
        static void Main() { Application.Run(new MainDlg()); }

        public MainDlg()
        {
            SuspendLayout();
            var button = new Button { Location = new System.Drawing.Point(7, 56), Size = new System.Drawing.Size(263, 23), Text = "Note size before and after clicking" };
            button.Click += Button_Click;
            ClientSize = new System.Drawing.Size(282, 253);
            Controls.Add(button);
            ResumeLayout(false);
            PerformLayout();
        }

        private void Button_Click(object sender, EventArgs e)
        {
            if (DateTime.Today.Year != 1234) return;    // This will always return
            try
            {
                // The following is never executed - but its very presence causes the dialog to shrink when running under VS2017
                BitmapFrame.Create((FileStream)null);   // Was using this to get metadata - that part works ok
                MessageBox.Show("Success");
            }
            catch { MessageBox.Show("Exception"); }
        }
    }
}

最佳答案

BitmapFrame是一个来自PresentationCore程序集的类,始终在WPF应用程序中使用。它具有一个模块初始化程序,可自动使该程序成为dpiAware。对于WPF应用程序而言,使用dpiAware非常重要。对于Winforms应用程序,应按be a feature键,但必须手动将其打开。

C#语言不支持module initializers。它大致类似于静态构造函数,但是在加载程序集时运行。程序集是由即时编译器加载的,这就是为什么看起来好像只有存在的语句才有所作为,而执行它并不重要。

因此,避免该问题的最佳方法是在创建第一个窗口之前,确保您的应用是dpiAware。单击链接以了解如何修改清单。如果不希望使用dpiAware,则在Winforms中编写dpiAware代码不是那么直观,那么您可以通过粘贴以下代码来禁用PresentationCore的功能:

[assembly:System.Windows.Media.DisableDpiAwareness]


这需要添加对WindowsBase的引用。您可以将其放在任何喜欢的位置,AssemblyInfo.cs是一个很合逻辑的地方。

10-04 14:48