Question

I have created a simple test form with FormBorderStyle = FixedToolWindow by default and added a button that will switch between FixedToolWindow and SizableToolWindow on mouse press.

Switching the FormBorderStyle between these two seems to produce a weird effect that's causing a lot of issues on my application. The problem is that the window seems to change size and I can't have that. I just want to change the border, I need the form size to remain the same.

For instance, here's the button code:

private void button1_Click(object sender, System.EventArgs e) {
    if(FormBorderStyle == FormBorderStyle.FixedToolWindow) {
        System.Diagnostics.Debug.WriteLine("SWITCHING: FIXED -> SIZABLE");
        FormBorderStyle = FormBorderStyle.SizableToolWindow;
    } else {
        System.Diagnostics.Debug.WriteLine("SWITCHING: SIZABLE -> FIXED");
        FormBorderStyle = FormBorderStyle.FixedToolWindow;
    }
}

And to debug I use this:

private void Settings_SizeChanged(object sender, System.EventArgs e) {
    System.Diagnostics.Debug.WriteLine(this.Size);
}

And here's the output when I press the switch button:

SWITCHING: FIXED -> SIZABLE
{Width=373, Height=169}
{Width=383, Height=179}
SWITCHING: SIZABLE -> FIXED
{Width=383, Height=179}
{Width=373, Height=169}

How can I fix this behavior? And by "fix", I mean, prevent this from happening if possible. I want to be able to specify my form size and to remain like that, no matter the type of border style.

Also, a solution by subclassing the Form class would be the perfect solution for me in case anyone as any ideas to solve this problem with such a method.

EDIT:
I made a little video to demonstrate the problem. The first test shows that the form size doesn't actually change (visually), only the location of the form changes a little bit; but the values for the Size property do change, as you can see on the debug output. The second test you will see on the debug output that the form Size property values change and the window size itself will also change.

Please look here:
http://screencast.com/t/0vT1vCoyx2u

Was it helpful?

Solution

Your issue is with the Location changing, not the Size. This code solves the problem seen in the video.

        private void Form1_DoubleClick(object sender, EventArgs e)
        {
            Point _location = this.PointToScreen(this.ClientRectangle.Location);
            if (this.FormBorderStyle == FormBorderStyle.SizableToolWindow)
            {
                this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
            }
            else
            {
                this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
            }
            Point _newloc = this.PointToScreen(this.ClientRectangle.Location);
            Size _diff = new Size(_newloc) - new Size(_location);
            this.Location -= _diff;
        }

It appears to me that the issue of the rendered form moving when switching between those two borderstyles is a bug in the DWM.

OTHER TIPS

I suspect what's happening is that Windows Forms is keeping the client size (i.e. inner area) the same while the border size changes. This is generally a good thing because it ensures that the window can still correctly fit the content that you've put on it.

If you want to maintain the same outer dimensions, you could work around it by saving the size to a variable before changing the border type, and then restoring it back. They'll probably a slight flicker, though.

This worked fine for me:

    private Size _size;
    private void Form1_DoubleClick(object sender, EventArgs e)
    {
        _size = this.Size;
        if (this.FormBorderStyle == FormBorderStyle.SizableToolWindow)
        {
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
        }
        else
        {
            this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
        }
        this.Size = _size;
    }

I had this same problem. The client size changes when you set the FormBorderStyle but it does not seem to get put into the clientrectangle property right away. The above listed code almost worked for me, but rather than just store size, make sure to store clientsize. Of course, in the above example maybe "this" was a reference to clientsize -- I wasn't sure. Buy anyway, this worked for me:

_frmFilter.Height = 300 Dim _size As Size = .ClientSize _frmFilter.FormBorderStyle = FormBorderStyle.FixedToolWindow _frmFilter.ClientSize = _size

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top