Saving out a Form’s Size and Location using the Application Settings feature


A very common requirement for Windows Forms applications is the ability to ‘remember’ the location and size of forms when they are closed, so that the next time they are shown, they can be restored to the former position. The Application Settings feature is .NET 2.0 makes it simple to do this, but unfortunately, it is a little hard to get it ‘just right’. This question is asked frequently on internal and external Microsoft forums, so I thought it warranted a blog post.


Now, the Windows Forms designer in Visual Studio 2005 provides a simple UI to data bind properties on controls to application settings. So the first thing that might occur to you is to simply bind the Form’s Location and Size properties to settings, add a line of code to save the settings class, and that’s it! Unfortunately, this is not the best option for a few reasons:



  1. First of all, you may notice that the Form.Size property is not offered up in the settings binding UI. This is because this property is marked DesignerSerializationVisibility.Hidden, so the designer doesn’t know how to serialize it, let alone generate a data binding for it. Instead, for Form, the ClientSize property is the one that gets serialized.
  2. So okay, maybe you can bind Location and ClientSize then? Well, yes, but this has another problem. Try setting it up and then attempt to resize the form from the left or top edge. You will see weird behavior. Why is this? It is beyond the scope of this post to give the full explanation, but it suffices to say that it has to do with how two way data binding works in the context of property sets that mutually affect each other (in the case of Location and ClientSize, both eventually call into a common method, SetBoundsCore()).
  3. This solution does not do the ‘right’ thing in the situation when the user maximized the form before closing it. In this case, you probably want to remember that the form was maximized, but also keep track of the last location/size before it was maximized, so you can restore it the next time the user hits the Restore button. You may want to handle the minimize case in a similar way too. The simple data binding solution does not do this right.
  4. Data binding to properties like Location and Size is just not efficient. Each time the user moves the form or resizes it, Windows sends hundreds of messages to the form, causing the  data binding logic to do a lot of processing, when all you want is just to store the last position and size before the form is closed.

The good news is that this is very easy to do with a few lines of code:



private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{

     Properties.Settings.Default.MyState = this
.WindowState;



if (this.WindowState == FormWindowState.Normal)


{


   Properties.Settings.Default.MySize = this.Size;


   Properties.Settings.Default.MyLoc = this.Location;


}


else


{


   Properties.Settings.Default.MySize = this.RestoreBounds.Size;


   Properties.Settings.Default.MyLoc = this.RestoreBounds.Location;


}



Properties.Settings.Default.Save();


}


private void Form1_Load(object sender, EventArgs e)


{



this.Size = Properties.Settings.Default.MySize;


this.Location = Properties.Settings.Default.MyLoc;


this.WindowState = Properties.Settings.Default.MyState;


}


By the way, speaking of Windows Forms 2.0, there is a lot of great new content on the WindowsForms.net site. Jessica has been actively blogging on interesting Windows Forms topics too.

Comments (10)

  1. Chris Conti says:

    Just be aware that it’s not really that simple- there’s a bunch of other things to consider to get it right- what if you start multiple instances, what if the screen resoltion changes since the last time the app was started, etc. check out http://blogs.msdn.com/oldnewthing/archive/2005/03/14/395271.aspx

  2. Tom Guinther says:

    I agree with Chris that you are doing a bit of a dis-service in that this code is not only overly simple, it doesn’t actually work.

    Two problems (outside of everything else that is wrong with this ‘sample’.)

    1) You probably don’t want to restore the previous window state unless it is Maximized.

    2) If Form.StartPosition != FormStartPosition.Manual, setting Location is pointless (unless you set it *after* the form is initially shown, which is so bogus you would never do that, right?)

    The cool thing is that you are showing people that RestoreBounds is the simple way to get the ‘previous’ size/location when the form is not in the Normal state.

  3. rprabhu says:

    These are good points. Yes, the solution above may not exactly be what you want, and you will likely need to tweak it a bit. It was mainly meant to point out why data binding doesn’t work very well for these properties, and to get you started along the right lines.

  4. Eric Cosky says:

    This kind of simple example of how to use project settings in it’s most basic manner would be a very good addition to the C# docs. I couldn’t find this kind of basic "how do you load/save settings" anywhere in the C# docs, it might be in there somewhere but if it was I couldn’t find it.

  5. Peter Ritchie says:

    Hmm, makes you wonder why Size is in the Advanced collection of DataBindings then.

  6. skain says:

    I don’t know what you people are complaining about.

    This little article gave me just what I needed to get started implementing my ‘form state saver’.

    Of course it’s not a cut and paste solution.  He never said it was.  But it’s certainly a useful introduction to an under-discussed topic.

  7. Gary says:

    Raghavendra:

     In your post "http://blogs.msdn.com/rprabhu/archive/2005/11/28/497792.aspx",  is "Properties" a .net class or your used-defined class? I could not find it in .net documentation.

    Gary

  8. rprabhu says:

    Gary: Properties is a class auto generated by Visual Studio in C# projects. It is part of the ‘My’ functionality added to VB/C# in VS 2005.

  9. HP's Weblog says:

    Bei der Internet Suche bin ich auf diesen Beitrag gestoßen …