3

This is very bizarre. I ported a project that was working fine under VS2008 but when I build it with VS2017, the very presence of one line causes my dialog to resize - the code does not even need to run, it just needs to be present in a subroutine that does run! I have created the simplest version of the program I could come up with to show this behavior. Try building/running under different versions of Visual Studio. I would love both an explanation for why this is happening as well as how to fix it. Thanks.

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"); }
        }
    }
}
Mick Bruno
  • 1,373
  • 15
  • 13
  • Ran this code in 2012 and in 2017, form never "resized" as you say, in either version. – LarsTech Nov 14 '17 at 22:57
  • Sorry, looks like this doesn't happen on all machines but is very consistent on those machines where it does occur. I will see if the tip by Hans Passant fixes this... – Mick Bruno Nov 15 '17 at 01:28

1 Answers1

5

BitmapFrame is a class that comes from the PresentationCore assembly, always used in a WPF app. It has a module initializer that automatically makes the program dpiAware. Being dpiAware is very important to a WPF app. And supposed to be a feature for a Winforms app, but it has to be turned on by hand.

The C# language has no support for module initializers. It is roughly similar to a static constructor, but runs when an assembly gets loaded. Assemblies get loaded by the just-in-time compiler, that is why it looked like just having the statement being present made the difference and executing it was not important.

So the best way to avoid the problem is to ensure your app is dpiAware before it creates its first window. Follow the link to learn how to modify the manifest. If it is undesirable to be dpiAware, writing dpiAware code in Winforms is not that intuitive, then you can disable what PresentationCore does by pasting this code:

[assembly:System.Windows.Media.DisableDpiAwareness]

Which requires adding a reference to WindowsBase. You can put it anywhere you like, AssemblyInfo.cs is a pretty logical place.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I didn't realize that PresentationCore was specific to WPF and that it could have unpleasant side effects when used in WinForms apps. Based on this info I found another method for getting the image metadata that I was looking for. So although I won't be using your tip, I will vote up your answer since it explained the problem and pointed me to the solution. – Mick Bruno Nov 15 '17 at 02:14