0
votes

I have a WinForms application, targeting .NET Framework 4.6.1. I need to restore the size, position, and location of all forms between runs of the application. This has already been achieved with the following:

private void saveMainWindowSettings()
{
    Properties.Settings.Default.MainWindowState = this.WindowState;
    if (this.WindowState == System.Windows.Forms.FormWindowState.Normal)
    {
        // save location and size if state is normal
        Properties.Settings.Default.MainWindowLocation = this.Location;
        Properties.Settings.Default.MainWindowSize = this.Size;
    }
    else
    {
        // save the RestoreBounds if the form is maximised or minimised
        Properties.Settings.Default.MainWindowLocation = this.RestoreBounds.Location;
        Properties.Settings.Default.MainWindowSize = this.RestoreBounds.Size;
    }

    // save the main window settings
    Properties.Settings.Default.Save();
}

private void loadMainWindowSettings()
{
    if (Properties.Settings.Default.MainWindowSize.Width == 0 || Properties.Settings.Default.MainWindowSize.Height == 0)
    {
        // first start
        // add default values (size 912x598)
        this.Size = new System.Drawing.Size(912, 598);
    }
    else
    {
         // load the remembered settings

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

         // we don't want a minimised window at startup
         if (this.WindowState == System.Windows.Forms.FormWindowState.Minimized)
                    this.WindowState = System.Windows.Forms.FormWindowState.Normal;

         this.Location = Properties.Settings.Default.MainWindowLocation;
         this.Size = Properties.Settings.Default.MainWindowSize;
     }
}

The saveMainWindowSettings() method is called in the FormClosing event handler, and the loadMainWindowSettings() method is called in the Load event handler.

However, there is an issue here when using multiple monitors. I have tested this code at home, with a laptop and an extra monitor, and it works fine. However, when testing with a different monitor, the window is not visible on the main screen (screen 1, the laptop display), because it was dragged to the other monitor in the previous setup. The window is open, as it is visible in the taskbar, but it cannot be seen at all, and cannot be dragged to the main screen. The only way to see it is to right-click it in the taskbar and maximise it.

To avoid this problem, I want to restore the window always to screen 1, so that it will be in the same state (minimised, maximised, normal), and the same relative size and position, accounting for differences in resolution. How can this be achieved?

1
You could use WIN+SHIFT to move the Form to the current Screen, or verify whether a Form is contained in the VirtualScreen bounds ([Rectangle].Contains([Rectangle]) or [Rectangle].IntersectsWith([Rectangle])) and move it to the into the VirtualScreen bound if it doesn't. Re-setting the Form's size ratio is different, since you don't know the original Screen Size, so you cannot rescale it proportionally. You can however resize it to fit the Screen or VirtualScreen bounds. The notes here may help: Using SetWindowPos with multiple monitorsJimi
With WIN+SHIFT I mean this combination plus a cursor key (LEFT and RIGHT keys, mostly, UP and DOWN if the Screens layout is vertical).Jimi

1 Answers

1
votes

I presume by "screen 1" you mean "primary display". All other displays are secondary, which may or may not exist when you run your app, and, if exist, may not be the same displays when you saved settings, nor may be in the same arrangement at the time of app start.

Look at this API: https://docs.microsoft.com/dotnet/api/system.windows.forms.screen.allscreens

You will have to do several things.

  1. When saving settings you have to translate the current window coordinates to desired coordinates on your primary display. This includes account for resolutions and scale factors of the current display and the primary monitor (if they are different). E.g. your primary monitor could be at 1920x1200 100% SF, and your secondary monitor when a form is at 2560x1440 125%. When calculating new coordinates you need to ensure the new coordinates don't end up outside visible area on the primary monitor.

  2. When persist information persist at 100% SF.

  3. When restore recalibrate the position if the primary monitor isn't at 100% SF, as well as ensure that the coordinates are within the visible area of the monitor (the primary monitor may have changed between the app runs).