.NET / Windows Forms: remember windows size and location

55,863

Solution 1

You'll need to save the window location and size in your application settings. Here's a good C# article to show you how.

EDIT

You can save pretty much anything you want in the application settings. In the Type column of the settings grid you can browse to any .NET type. WindowState is in System.Windows.Forms and is listed as FormWindowState. There's also a property for FormStartPosition.

Solution 2

If you add this code to your FormClosing event handler:

if (WindowState == FormWindowState.Maximized)
{
    Properties.Settings.Default.Location = RestoreBounds.Location;
    Properties.Settings.Default.Size = RestoreBounds.Size;
    Properties.Settings.Default.Maximised = true;
    Properties.Settings.Default.Minimised = false;
}
else if (WindowState == FormWindowState.Normal)
{
    Properties.Settings.Default.Location = Location;
    Properties.Settings.Default.Size = Size;
    Properties.Settings.Default.Maximised = false;
    Properties.Settings.Default.Minimised = false;
}
else
{
    Properties.Settings.Default.Location = RestoreBounds.Location;
    Properties.Settings.Default.Size = RestoreBounds.Size;
    Properties.Settings.Default.Maximised = false;
    Properties.Settings.Default.Minimised = true;
}
Properties.Settings.Default.Save();

It will save the current state.

Then add this code to your form's OnLoad handler:

if (Properties.Settings.Default.Maximised)
{
    Location = Properties.Settings.Default.Location;
    WindowState = FormWindowState.Maximized;
    Size = Properties.Settings.Default.Size;
}
else if (Properties.Settings.Default.Minimised)
{
    Location = Properties.Settings.Default.Location;
    WindowState = FormWindowState.Minimized;
    Size = Properties.Settings.Default.Size;
}
else
{
    Location = Properties.Settings.Default.Location;
    Size = Properties.Settings.Default.Size;
}

It will restore the last state.

It even remembers which monitor in a multi monitor set up the application was maximised to.

Solution 3

Previous solutions didn't work for me. After playing a while I ended up with following code which:

  • preserves maximised and normal state
  • replaces minimised state with default position
  • in case of screen size changes (detached monitor, remote connection,...) it will not get user into frustrating state with application open outside of screen.

    private void MyForm_Load(object sender, EventArgs e)
    {
        if (Properties.Settings.Default.IsMaximized)
            WindowState = FormWindowState.Maximized;
        else if (Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(Properties.Settings.Default.WindowPosition)))
        {
            StartPosition = FormStartPosition.Manual;
            DesktopBounds = Properties.Settings.Default.WindowPosition;
            WindowState = FormWindowState.Normal;
        }
    }
    
    private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        Properties.Settings.Default.IsMaximized = WindowState == FormWindowState.Maximized;
        Properties.Settings.Default.WindowPosition = DesktopBounds;
        Properties.Settings.Default.Save();
    }
    

user settings:

    <userSettings>
    <WindowsFormsApplication2.Properties.Settings>
        <setting name="WindowPosition" serializeAs="String">
            <value>0, 0, -1, -1</value>
        </setting>
        <setting name="IsMaximized" serializeAs="String">
            <value>False</value>
        </setting>
    </WindowsFormsApplication2.Properties.Settings>
</userSettings>

Note: the WindowsPosition is intentionally wrong, so during first launch application will use default location.

Note that IntersectsWith expects a Rectangle, not a Point. So unlike other answers, this answer is saving the DesktopBounds, not Location, into Properties.Settings.Default.WindowPosition

Solution 4

I tried a few different methods; this is what ended up working for me. (In this case - on first launch - the defaults haven't been persisted yet, so the form will use the values set in the designer)

  1. Add the settings to the project (manually - don't rely on visual studio): Properties.Settings

  2. Add the following code to your form:

    private void Form1_Load(object sender, EventArgs e)
    {
        this.RestoreWindowPosition();
    }
    
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        this.SaveWindowPosition();
    }
    
    private void RestoreWindowPosition()
    {
        if (Settings.Default.HasSetDefaults)
        {
            this.WindowState = Settings.Default.WindowState;
            this.Location = Settings.Default.Location;
            this.Size = Settings.Default.Size;
        }
    }
    
    private void SaveWindowPosition()
    {
        Settings.Default.WindowState = this.WindowState;
    
        if (this.WindowState == FormWindowState.Normal)
        {
            Settings.Default.Location = this.Location;
            Settings.Default.Size = this.Size;
        }
        else
        {
            Settings.Default.Location = this.RestoreBounds.Location;
            Settings.Default.Size = this.RestoreBounds.Size;
        }
    
        Settings.Default.HasSetDefaults = true;
    
        Settings.Default.Save();
    }
    

Solution 5

If you use the fabulous open source library - Jot, you can forget about the tedious .settings files and just do this:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

There's a Nuget package as well, and you can configure pretty much everything about how/when/where data is stored.

Disclaimer: I'm the author, but the library is completely open source (under MIT license).

Share:
55,863
clamp
Author by

clamp

hello

Updated on November 02, 2020

Comments

  • clamp
    clamp over 3 years

    I have a Windows Forms application with a normal window. Now when I close the application and restart it, I want that the main window appears at the same location on my screen with the same size of the moment when it was closed.

    Is there an easy way in Windows Forms to remember the screen location and window size (and if possible the window state) or does everything have to be done by hand?

  • clamp
    clamp over 14 years
    thanks, that is a good article. only thing left is to remember the windowstate (maximized, minimized, ...) how can i put that one to the settings?
  • clamp
    clamp over 14 years
    yes thanks. i didnt realize that you can browse to all types of .NET in these settings at first.
  • clamp
    clamp over 14 years
    thanks! one more thing: if the window is maximized, how can i remember which monitor it is maximized on in a multi-monitor setup?
  • Walter
    Walter over 14 years
    Add the monitor id to the application settings as well.
  • clamp
    clamp over 14 years
    thanks, but i couldnt find a way to get the monitor id. i only found the Screen object, but it doesnt seem to have something unique associated with it.
  • JohnForDummies
    JohnForDummies over 14 years
    Again, I'm sorry, I can't add a comment to the other thread... But Matt, by setting the location of the form, it will move it to the correct screen, and then you can set the WindowState to Maximized, etc, and it will be on the correct screen.
  • Don Kirkby
    Don Kirkby about 13 years
    @clamp, I expect if you set the window position and then set the window state to maximized, it will maximize to cover whichever monitor it is in. If you record the window position and window state at shut down, and then apply the window position before the window state at start up, then it should maximize back where it was.
  • rob
    rob about 11 years
    For those of you that haven't used Properties.Settings before you'll need to go into your project properties and go to the settings tab. Create a default settings file and add a property called Location and one called Size.
  • EricLaw
    EricLaw almost 11 years
    Your location storage code fails if the form is Minimized. You need to also check for FormWindowState.Minimized too. Is "Maximised" a typo for "Maximized"?
  • ChrisF
    ChrisF almost 11 years
    @EricLaw - "Maximised" is the name of the property. I suppose it should be "Maximized" for consistency. Re checking for "Minimized" - it was something I didn't have in the app I took this from.
  • Valamas
    Valamas over 10 years
    @rob: Cheers for the reminder on settings. ALSO: I tried and failed to move this code into a static helper class. Has anyone had such luck?
  • Glenn Maynard
    Glenn Maynard almost 10 years
    You need to set WindowState after setting Location. Otherwise, the window will always be maximized on the default monitor, since the maximized location is based on Location at the time you set WindowState. That means that when the user maximizes it on his secondary monitor, it'll restore on the primary monitor instead.
  • CularBytes
    CularBytes about 9 years
    what is RestoreBounds? Does not exist, can't find a reference eather
  • ChrisF
    ChrisF about 9 years
    @RageCompex - RestoreBounds is a property of the System.Windows.Forms.Form class, so your app needs to be derive from that in order to use it.
  • Rodrigo
    Rodrigo almost 7 years
    IT WORKED! But with some extra work for adding ApplicationSettings -> PropertyBinding thing (I'm not into .NET etc and all got too complex). More info below. In 2017, using a Windows Application targeting .NET Framework 4.5.2 I had to follow the steps pointed in this blog post to create the needed properties xldennis.wordpress.com/2010/03/19/…
  • it3xl
    it3xl over 4 years
    Jot is amateur solution. Let your form to remember a position on a second monitor, disable the monitor and you won't see your form. In some cases you will never see it as Windows window positioning buttons may be ignored. Imagine happy customers and support teams now. I haven't researched how but it changes the layout of forms. WTF? Jot activities on the Location property will be ignored if StartPosition property isn't set to the Manual. And so on, and so on. But this is a nice try. Let it be.
  • anakic
    anakic over 4 years
    Hey. Multiple displays (the scenario with unplugging) is addressed in the github readme in the "real world form/window tracking" section as well as using callbacks for handling special cases like minimized windows. The above code is simplistic for illustration purposes. It's also a bit out of date. If you're up for submitting an issue (or a pull request) for any scenario in particular that'd be great.
  • it3xl
    it3xl over 4 years
    I should have been consider it as a library, not as a framework. I'll read the readme. Many thanks.
  • anakic
    anakic over 4 years
    Yeah, it's ~500 lines of code without whitespace and comments, so it's fairly small. I'd definitely call it a library, even though it can integrate with ioc containers and work as infrastructure.
  • TinyRacoon
    TinyRacoon over 4 years
    Good solution. If you saved WindowState as type System.Windows.Forms.FormWindowState in settings it would saving having the max and min flags. X
  • Joan Charmant
    Joan Charmant over 3 years
    This one worked for me with the exception that if the window is maximized on the second screen it's restored maximized on the main screen. The desktop bounds should be restored before setting the state (if it intersects).