Click here to Skip to main content
13,447,300 members (38,948 online)
Click here to Skip to main content
Add your own
alternative version


30 bookmarked
Posted 19 May 2006

Save and restore the state of a Windows Form in .NET 2.0

, 19 May 2006
Rate this:
Please Sign up or sign in to vote.
A class that will save and restore window state, size, and position for a Form in .NET 2.0.


The class saves the state (location, size and windows state) of a form to registry (under HKEY_CURRENT_USER) when the form is closed and restores the form state when it is loaded. (To work with .NET 1.x one need to use some other events and a couple of methods are new to .NET 2.0).

It will also work with multi screen desktops. The key here is to use Form.DesktopBounds and not Form.Location and Form.Size. Also i case of screens not always being there I use Screen.GetBounds() to check and if needed move form to an existing screen.

To use just include the following line in the constructor of your Form:

FormState formState = new FormState(this, "SampleApp");

Also got some methods for storing and getting other settings regarding the form in registry (SaveValue(), GetValue(), GetIntValue()). Use these in the FormClosed and Load event handlers store and restore whatever... (need to keep the FormState object as a variable of your form class in this case).

The class:

using System;
using System.Drawing;
using Microsoft.Win32;
using System.Windows.Forms;

/// <summary>
/// Create an instance of this class in the constructor of a form. 
/// Will save and restore window state, size, and position.
/// Uses DesktopBounds (instead of just Form.Location/Size) 
/// to place window correctly on a multi screen desktop.
/// </summary>
class FormState
  private Form _parent;
  private string _registry_key;

  /// <summary>
  /// Initializes an instance of the FormState class.
  /// </summary>
  /// <param name="parent">
  /// The form to store settings for.
  /// </param>
  /// <param name="sub_key">
  /// Registry path from HKEY_CURRENT_USER to place for storing settings.
  /// Will create a subkey named "FormState".
  /// </param>
  public FormState(Form parent, string subkey)
    this._parent = parent;
    this._registry_key = subkey + "\\FormState";
    this._parent.Load += new EventHandler(On_Load);
    this._parent.FormClosed += new FormClosedEventHandler(On_FormClosed);

  public void SaveValue(string name, object value)
    this.RegKey.SetValue(name, value);

  public object GetValue(string name, object default_value)
    return this.RegKey.GetValue(name, default_value);

  /// <summary>
  /// If for some reason the value stored in reg cannot be parsed to int 
  /// the default_value is returned.
  /// </summary>
  public int GetIntValue(string name, int default_value)
    int val = default_value;
    if (!int.TryParse(this.RegKey.GetValue(name, default_value).ToString(), out val))
      val = default_value;
    return val;

  private RegistryKey RegKey
      return Registry.CurrentUser.CreateSubKey(
        this._registry_key + "\\" + this._parent.Name); 

  private void On_Load(object sender, EventArgs e)
    int X, Y, width, height, window_state;

    // place to get settings from
    RegistryKey key = this.RegKey;

    if (!int.TryParse(key.GetValue("DesktopBounds.Width", 
      out width))
      width = this._parent.DesktopBounds.Width;
    if (!int.TryParse(key.GetValue("DesktopBounds.Height", 
      out height))
      height = this._parent.DesktopBounds.Height;
    if (!int.TryParse(key.GetValue("DesktopBounds.X", 
      out X))
      X = this._parent.DesktopBounds.X;
    if (!int.TryParse(key.GetValue("DesktopBounds.Y", 
      out Y))
      Y = this._parent.DesktopBounds.Y;

    // In case of multi screen desktops, check if we got the
    // screen the form was when closed.
    // If not there we put it in upper left corner of nearest 
    // screen.
    // We don't bother checking size (as long as the user see
    // the form ...).
    Rectangle screen_bounds = Screen.GetBounds(new Point(X, Y));
    if (X > screen_bounds.X + screen_bounds.Width)
      X = screen_bounds.X;
      Y = screen_bounds.Y;

    this._parent.DesktopBounds = new Rectangle(X, Y, width, height);
    if (!int.TryParse(key.GetValue("WindowState", 
      out window_state))
      window_state = (int)this._parent.WindowState;
    this._parent.WindowState = (FormWindowState)window_state;

  private void On_FormClosed(object sender, FormClosedEventArgs e)
    // There may be cases where the event is raised twice.
    // To avoid handling it twice we remove the handler.
    this._parent.FormClosed -= new FormClosedEventHandler(On_FormClosed);
      // TODO: find out why it is raised twice ...

    // place to store settings
    RegistryKey key = this.RegKey;

    // save window state
    key.SetValue("WindowState", (int)this._parent.WindowState);
    // save pos & size in normal window state
    if (this._parent.WindowState != FormWindowState.Normal)
      this._parent.WindowState = FormWindowState.Normal;
    key.SetValue("DesktopBounds.Y", this._parent.DesktopBounds.Y);
    key.SetValue("DesktopBounds.X", this._parent.DesktopBounds.X);
    key.SetValue("DesktopBounds.Width", this._parent.DesktopBounds.Width);
    key.SetValue("DesktopBounds.Height", this._parent.DesktopBounds.Height);

A note on the FormClosed event. When the main form (used in Application.Run()) is closed, the application quits and all forms created after the main form was created are also closed. One would think that the FormClosing and FormClosed event would be raised for all forms. This does not seem to be the case.

I solve this by using the following in the main form:

private void On_FormClosing(object sender, FormClosingEventArgs e)
  this.FormClosing -= new FormClosingEventHandler(On_FormClosing);

private void On_FormClosed(object sender, FormClosedEventArgs e)
  this.FormClosed -= new FormClosedEventHandler(On_FormClosed);
in the FormClosing event for the main form of the application. This raises the FormClosing and FormClosed event for all open forms.

Passing the FormClosingEventArgs param to Application.Exit() gives the other forms a chance to cancel quitting the application.

Removing the FormClosing and FormClosed delegates prevents the methods from being called a second time (as Application.Exit() will raise the events for the main form as well as the others).

This class was created after having used various laboursome methods over the years and finally getting tired of it.

Various articles and blogs on the internet including an article ("Saving and Restoring the Location, Size and Windows State of a .NET Form") by Joel Matthias here on the Code Project was the inspiration for this class.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

No Biography provided

You may also be interested in...

Comments and Discussions

GeneralRetaining the order in which the windows are opened Pin
juhi0923-Sep-08 19:59
memberjuhi0923-Sep-08 19:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180318.3 | Last Updated 20 May 2006
Article Copyright 2006 by Stein-Tore Erdal
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid