Reputation: 701
I have been looking around SO and found these two articles:
The problem is that these article is in the ball park of my problem, yet I can't use them as I see it (unless I make my solution really complicated). While the article talk about restoring a Form when they have closed their application completely, that is not exactly what I am trying is to accomplish.
What I am doing is closing and opening the same form within the same running application. When this happen I want it to have the same exact location, state and size as it where when i closes. This is straight forward because I can save the location, state and size from the form object, dispose it and apply the old values to my new form. This works, but if I have a maximized window on monitor 2, and the close/open function runs, it opens the form maximized on monitor 1.
Is there any easy way to keep it on monitor 2 in the case above, or do I have to dive into complicated libraries?
Upvotes: 4
Views: 2840
Reputation: 1
I have created an extension method that will work whether you are closing the app or just the current window. I call RestoreLastLocation on the form_load event and SaveLastLocation on the form_closing event. This is old code so I apologize if its a bit crude.
public static void SaveLastLocation(this Form form, string UniqueName)
{
FormWindowState CurState = form.WindowState;
if (CurState == FormWindowState.Minimized)
CurState = FormWindowState.Normal;
form.WindowState = FormWindowState.Normal;
if (Properties.Settings.Default.WindowSettings == null)
Properties.Settings.Default.WindowSettings = new System.Collections.Specialized.StringCollection();
if(Properties.Settings.Default.WindowSettings.Count > 0)
foreach (string S in Properties.Settings.Default.WindowSettings)
if (S.Split('|').First().ToLower() == UniqueName.ToLower())
{
Properties.Settings.Default.WindowSettings.Remove(S);
break;
}
Properties.Settings.Default.WindowSettings.Add(string.Format("{0}|{1}|{2}|{3}|{4}|{5}",
UniqueName, form.Top.ToString(), form.Left.ToString(), form.Height.ToString(), form.Width.ToString(), form.WindowState.ToString()));
Properties.Settings.Default.Save();
}
public static void RestoreLastLocation(this Form form, string UniqueName)
{
if (Properties.Settings.Default.WindowSettings != null && Properties.Settings.Default.WindowSettings.Count > 0)
foreach (string S in Properties.Settings.Default.WindowSettings)
{
string[] Parts = S.Split('|');
if (Parts[0].ToLower() == UniqueName.ToLower())
{
form.Top = int.Parse(Parts[1]);
form.Left = int.Parse(Parts[2]);
form.Height = int.Parse(Parts[3]);
form.Width = int.Parse(Parts[4]);
form.WindowState = (FormWindowState)Enum.Parse(typeof(FormWindowState), Parts[5]);
break;
}
}
}
Upvotes: 0
Reputation: 701
Following Hans Passant instructions in the comment in the original post, and setting the values correctly solved the problem. I now do like this in my Forms OnLoad event:
if(UseGivenpositioningValues)
{
Location = OverrideLocation;
if (OverrideWindowState == FormWindowState.Normal)
Size = OverrideSize;
WindowState = OverrideWindowState;
UseGivenpositioningValues = false;
}
Location first, then the state. It's not a perfect solution as Justin pointed out in his answer, since a user can change his setup and then the Form could appear off screen if the user changes his setup. However in my specific case, this is not an issue.
Upvotes: 0
Reputation: 776
Try this...
(Form2 is the form you want to position. Modify as needed. )
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
static System.Drawing.Point _location = new Point();
static System.Drawing.Size _size;
static FormWindowState _state;
public Form2()
{
InitializeComponent();
this.Load += new EventHandler( Form2_Load );
this.FormClosing += new FormClosingEventHandler( Form2_FormClosing );
}
void Form2_Load( object sender, EventArgs e )
{
// Restore the Form's position.
//
// Handle possibility that our previous screen location is no longer valid for
// the current display environment (i.e., multiple->single display system).
//
Point location = _location;
if ( location == new Point( 0, 0 ) || !IsScreenLocationValid( location ) )
{
if ( null != this.Parent )
this.StartPosition = FormStartPosition.CenterParent;
else
this.StartPosition = FormStartPosition.CenterScreen;
}
else
{
this.Location = location;
// Ensure that the Form's size is not smaller than its minimum allowed.
//
Size size = _size;
size.Width = System.Math.Max( size.Width, this.MinimumSize.Width );
size.Height = System.Math.Max( size.Height, this.MinimumSize.Height );
this.Size = size;
}
// Only restore the Form's window state if it is not minimized.
// (If we restore it as minimized, the user won't see it).
//
if ( _state == FormWindowState.Normal || _state == FormWindowState.Maximized )
{
this.WindowState = _state;
}
}
/// <summary>
/// Determines if the given screen location is valid for the current display system.
/// </summary>
/// <param name="location">A Point object describing the location</param>
/// <returns>True if the location is valid; otherwise, false</returns>
static bool IsScreenLocationValid( Point location )
{
Rectangle screenBounds = System.Windows.Forms.Screen.GetBounds( location );
return screenBounds.Contains( location );
}
void Form2_FormClosing( object sender, FormClosingEventArgs e )
{
_state = this.WindowState;
if ( _state == FormWindowState.Normal )
{
_location = this.Location;
_size = this.Size;
}
else
{
_location = this.RestoreBounds.Location;
_size = this.RestoreBounds.Size;
}
}
}
}
Upvotes: 1
Reputation: 86789
If I were you I would consider your problem to be a simple extension of those linked questions, the only change being that your application isn't being closed - only the window is (so you don't need to persist this information to disk, just keep it in memory).
The reason being that users can (and eventually one of them probably will) change display configuration (number of displays, display positions etc...) while your application is running (e.g. a laptop user unplugging an external screen), and so if you don't take this into account you will end up positioning your windows off screen where they can't be accessed by the user.
Upvotes: 1