tags:

views:

86

answers:

2

Is there an easy way to determine the size of a Form it does have in WindowState=Normal, without actually changing the Form state?

Here is what I do now (C# code):

public class MyForm: Form
{
     public void MyMethod()
     {
          // ...
          FormWindowState oldState = this.WindowState;
          this.WindowState = FormWindowState.Normal;

          Point windowLocation = this.Location;
          Size windowSize = this.Size;

          this.WindowState = oldState;
          //  ...
     }
}

This is what I would like the code to look like:

public class MyForm: Form
{
     public void MyMethod()
     {
          // no state change here
          Point windowLocation = this.NormalStateLocation;
          Size windowSize = this.NormalStateSize;
     }
}

In fact there are no NormalStateLocation or NormalStateSize properties in Windows Forms.

+1  A: 

try this

    private Size _normalSize;
    private Point _location;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        this.LocationChanged += new EventHandler(Form1_LocationChanged);
        this.SizeChanged += new EventHandler(Form1_SizeChanged);
    }

    void Form1_SizeChanged(object sender, EventArgs e)
    {
        if (this.WindowState == FormWindowState.Normal)
        {
            this._normalSize = this.Size;
        }
    }

    void Form1_LocationChanged(object sender, EventArgs e)
    {
        if (this.WindowState == FormWindowState.Normal)
        {
            this._location = this.Location;
        }
    }
Seattle Leonard
This is a valid solution, of course, but since Windows knows the size of the form when restoring the window from minimized to normal state, the information must be already stored somewhere internally. Isn't there a way to get that size directly?
Doc Brown
+1  A: 

The Load event is the earliest possible moment to find out what the "normal" size of the form will be. At that point, any scaling induced by AutoSizeMode and any user overrides to border and caption sizes have been applied. However, that size will only be valid if the WindowState is not set to Minimized in the designer. You'll have to wait until the form is at least shown once in the Normal state.

Also beware that the size you'll get is faked if you run with Aero fat borders enabled. Vista and Win7 intentionally return a window size that would be reported if earlier operating systems ran your program. If this really matters, you'll have to use Editbin.exe to mark your program Vista compatible.

Bear traps out there, try to avoid having to ask the question. You can always change the window location or size when you get the Resize event.


If this is only to memorize the form location and size then you'll want to use Settings. Use Project + Properties, Settings tab to add them. You cannot use the automatic ApplicationSettings binding because you don't want to save the location and size of the form when it is minimized or maximized. Make it look like this:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }
    protected override void OnLoad(EventArgs e) {
        if (Properties.Settings.Default.Form1Size.Width > 0) {  // Valid?
            this.Size = Properties.Settings.Default.Form1Size;
            this.Location = Properties.Settings.Default.Form1Location;
        }
        base.OnLoad(e);
    }
    protected override void OnLocationChanged(EventArgs e) {
        if (this.WindowState == FormWindowState.Normal) 
            Properties.Settings.Default.Form1Location = this.Location;
        base.OnLocationChanged(e);
    }
    protected override void OnResize(EventArgs e) {
        if (this.WindowState == FormWindowState.Normal)
            Properties.Settings.Default.Form1Size = this.Size;
        base.OnResize(e);
    }
    protected override void OnFormClosed(FormClosedEventArgs e) {
        Properties.Settings.Default.Save();
        base.OnFormClosed(e);
    }
}
Hans Passant
It does not matter, I just want to remmber the size and location to make it persistent and restore it when the Form is reopened again.
Doc Brown
@Doc, okay I now what you mean now. Post updated.
Hans Passant
@That's basically the same approach Seattle Leonard posted. I give you +1, too, but I would be more happy if one knows how to get the internally stored size and location.
Doc Brown
You'd have to P/Invoke GetWindowPlacement().
Hans Passant
@Hans Passant: if you provide us with a working example, I would be happy to accept your answer.
Doc Brown
Do you want a warranty with that? You've got everything you need to hire somebody at rentacoder.com
Hans Passant
@Hans: take it easy, I was just thinking you might have an example at hand how to use GetWindowPlacement correctly from C# together with WinForms. I suspect there are some pitfalls to avoid.
Doc Brown
Well okay. There are pitfalls, the first part of my post explained them. Visit pinvoke.net for the required declarations.
Hans Passant