Many posts around about restoring a WinForm position and size.
Examples:
But I have yet to find code to do this with multiple monitors.
That is, if I close my .NET Winform app with the window on monitor 2, I want it to save the windows size, location, and state to the application settings, so it could later restore to monitor 2 when I restart the app. It would be nice if, like in the codeproject example above, it includes some sanity checks, as in if the saved location is mostly off-screen it "fixes" it. Or if the saved location is on a monitor that is no longer there (e.g. my laptop is now by itself without my second monitor) then it correctly moves it to monitor 1.
Any thoughts?
My environment: C#, .NET 3.5 or below, VS2008
In Windows 10, 8, 7, and Vista, hold down the “Shift” key while right-clicking the program in the taskbar, then select “Move“. In Windows XP, right-click the item in the task-bar and select “Move“. In some instances, you may have to select “Restore“, then go back and select “Move“.
To save any window position, click on the Windows title bar to make sure the window is active and press the hotkey Ctrl+Alt+Z. A tooltip message will confirm that the position has been saved.
Try this code. Points of interest:
The bounds and state are stored in the appsettings with their corresponding type so there's no need to do any string parsing. Let the framework do its serialization magic.
public partial class MainForm : Form { public MainForm() { InitializeComponent(); // this is the default this.WindowState = FormWindowState.Normal; this.StartPosition = FormStartPosition.WindowsDefaultBounds; // check if the saved bounds are nonzero and visible on any screen if (Settings.Default.WindowPosition != Rectangle.Empty && IsVisibleOnAnyScreen(Settings.Default.WindowPosition)) { // first set the bounds this.StartPosition = FormStartPosition.Manual; this.DesktopBounds = Settings.Default.WindowPosition; // afterwards set the window state to the saved value (which could be Maximized) this.WindowState = Settings.Default.WindowState; } else { // this resets the upper left corner of the window to windows standards this.StartPosition = FormStartPosition.WindowsDefaultLocation; // we can still apply the saved size this.Size = Settings.Default.WindowPosition.Size; } } private bool IsVisibleOnAnyScreen(Rectangle rect) { foreach (Screen screen in Screen.AllScreens) { if (screen.WorkingArea.IntersectsWith(rect)) { return true; } } return false; } protected override void OnClosed(EventArgs e) { base.OnClosed(e); // only save the WindowState if Normal or Maximized switch (this.WindowState) { case FormWindowState.Normal: case FormWindowState.Maximized: Settings.Default.WindowState = this.WindowState; break; default: Settings.Default.WindowState = FormWindowState.Normal; break; } // reset window state to normal to get the correct bounds // also make the form invisible to prevent distracting the user this.Visible = false; this.WindowState = FormWindowState.Normal; Settings.Default.WindowPosition = this.DesktopBounds; Settings.Default.Save(); } }
The settings file for reference:
<?xml version='1.0' encoding='utf-8'?> <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ScreenTest" GeneratedClassName="Settings"> <Profiles /> <Settings> <Setting Name="WindowPosition" Type="System.Drawing.Rectangle" Scope="User"> <Value Profile="(Default)">0, 0, 0, 0</Value> </Setting> <Setting Name="WindowState" Type="System.Windows.Forms.FormWindowState" Scope="User"> <Value Profile="(Default)">Normal</Value> </Setting> </Settings> </SettingsFile>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With