Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restoring Window Size/Position With Multiple Monitors

Many posts around about restoring a WinForm position and size.

Examples:

  • www.stackoverflow.com/questions/92540/save-and-restore-form-position-and-size
  • www.codeproject.com/KB/dialog/restoreposition.aspx?fid=1249382&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2595746

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

like image 323
Michael Sorens Avatar asked Jun 01 '09 23:06

Michael Sorens


People also ask

How do you reset a Windows position?

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“.

How do I save a position in Windows 10?

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.


1 Answers

Try this code. Points of interest:

  • Checks if the window is (partially) visible on any screen's working area. E.g. dragging it behind the task bar or moving it completely offscreen resets the position to windows default.
  • Saves the correct bounds even if the Form is minimized or maximized (common error)
  • Saves the WindowState correctly. Saving FormWindowState.Minimized is disabled by design.

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> 
like image 180
VVS Avatar answered Sep 23 '22 13:09

VVS