Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switched to VS 2012 and now form doesnt resize properly?

I switched to VS 2012 yesterday from VS 2010 and all seemed to go well except this.

I have a button on my form that when pressed extends the width of the form to show additional controls. Press the button again and it reduces the width to hide those controls. Now all of this worked great in VS 2010 and also works fine when I debug in VS 2012 but as soon as I publish or compile the project and open the .exe when you click on the button it adds like 5 to the width instead of the 100+ it needs to. I click it again and it will then change it to 372 like it should and shows all my controls. I click it again to hide the controls and it hides the controls partially (goes to the 188 + the mysterious 5) I hope all of this makes sense and am hoping there is a better way to run the process I need to.

Here is the code I am currently working with and I didn't change anything between switching from 2010 to 2012. In fact, if I open this same solution in 2010 and publish everything works fine.

    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 = ">>";

    }
like image 225
Nabbic Avatar asked Apr 12 '13 22:04

Nabbic


1 Answers

The width of your form hasn't been 188 pixels in a long time. Now with VS2012, Windows finally stops lying about it.

At issue are the fat window borders in Aero. They were an extreme appcompat problem when the feature was introduced in Vista. Very necessary because those two pixels where getting hard to hit with a mouse. But drastically incompatible with the way an application creates a window. It asks for a specific window size, the outer size, the nWidth and nHeight arguments of the CreateWindow() function. But what really matters is the size of the client area, the part of the window inside the borders. If Microsoft wouldn't have done something about it, old applications would have ended up with a client area that was too small. Which looks very bad, the window content would not fit anymore. A control towards the bottom or right side of the form would not be completely displayed for example.

So, sneakily, Aero makes the window larger by the extra width of the fat borders. And when the app asks for the window size, it sneakily says that it is smaller by the same added width. The app doesn't know any better than it is still running with the same window size it had on XP. This works pretty well, but is not exactly ideal. Hard to get window edges to align properly with that lie for example.

Whether or not Aero will lie about the window size is based on the target operating system recorded in the EXE header. When it sees a version older then 6.00, the Vista version number, then it will assume that your EXE is a legacy program that doesn't know about the fat border feature. So needs to be lied to. You've been running with that target version number set to 4.00 for a long time, it is written by the .NET compiler when it builds your program. You can see it with dumpbin.exe /headers yourapp.exe.

This finally changed in VS2012 and .NET 4.5. Which is a .NET version that is not available in XP. The compiler can finally make the hard assumption that XP is history and you are going to run on a version of Windows that supports Aero. So it sets the target Windows version in the EXE header to 6.00. Correspondingly, Aero will now stop lying about the window size. You get the real one, not the faked one.

So a quick fix is to change the target .NET framework version to 4.0. That's available on XP so you'll get lied to again.

Of course it is better to fix your code. Never use the Size, Width or Height property, they'll inevitably depend on the border and caption size. Use the ClientSize property instead, that's the stable one and the one you really care about. But be careful with that property as well, a form may rescale when it runs on a machine that has its video adapter set to more than 96 dots per inch. Another feature that's very accessible in Vista and up. Rescaling changes the ClientSize proportionally by the DPI setting.

The real fix is to use a bool field instead that keeps track of the window state. And set the ClientSize property based on the position of a control you want to hide or reveal. So roughly:

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

Replace someControl in this code with the name of your controls.

like image 129
Hans Passant Avatar answered Nov 08 '22 17:11

Hans Passant