Storing form size

J

Jeff Johnson

To be user-friendly, I like to store the size and position of a window so
that it can be opened in the same place the next time the user starts the
app. Ideally, I would simply retrieve this information during the
FormClosing event, but if the window is minimized at the time you get the
minimized size and not the "restored" size. (The one thing I don't want to
do is start the app minimized; it either opens at its last restored size or
maximized.) Because of this I record the form's position and size during
every Move or Resize event, but that seems clunky. Is there any way to ask
(.NET framework method or API call, I don't care) a minimized window what
its restored size and position are?
 
U

Udo Nesshoever

=== original message ===
from: Jeff Johnson
date: 14.07.2008 15:44
To be user-friendly, I like to store the size and position of a window so
that it can be opened in the same place the next time the user starts the
app. Ideally, I would simply retrieve this information during the
FormClosing event, but if the window is minimized at the time you get the
minimized size and not the "restored" size. (The one thing I don't want to
do is start the app minimized; it either opens at its last restored size or
maximized.) Because of this I record the form's position and size during
every Move or Resize event, but that seems clunky. Is there any way to ask
(.NET framework method or API call, I don't care) a minimized window what
its restored size and position are?

Derive your forms from this class and the rest works automatically:

public class ExPositionedForm : Form
{
public ExPositionedForm()
{
if (!DesignMode)
{
Load += PositionedForm_Load;
FormClosing += PositionedForm_FormClosing;
} // if ()
} // ExPositionedForm()

private void PositionedForm_Load(object sender, EventArgs e)
{
if (!DesignMode)
{
LoadSettings();
} // if ()
} // PositionedForm_Load(sender, e)

private void PositionedForm_FormClosing(
object sender, FormClosingEventArgs e)
{
if (!DesignMode)
{
SaveSettings();
} // if ()
} // PositionedForm_FormClosing(sender, e)

private void SaveSettings()
{
string m_RegPath = ConfigurationManager.AppSettings["RegPath"];
if (m_RegPath != null && m_RegPath.Length > 0)
{
using (RegTools rt = new RegTools(m_RegPath))
{
rt.Save(Name + "State", (int)WindowState);
Rectangle rect = (WindowState == FormWindowState.Normal) ?
Bounds : RestoreBounds;
rt.Save(Name + "Bounds", rect);
} // using
} // if (m_RegPath.Length)
} // SaveSettings()

private void LoadSettings()
{
string m_RegPath = ConfigurationManager.AppSettings["RegPath"];
if (m_RegPath != null && m_RegPath.Length > 0)
{
using (RegTools rt = new RegTools(m_RegPath))
{
Rectangle rec = rt.Load(Name + "Bounds", Bounds);
Rectangle maxRec = SystemInformation.VirtualScreen;
int posLeft = (rec.Left > maxRec.Width) ?
maxRec.Width - rec.Width : rec.Left;
int posTop = (rec.Top > maxRec.Height) ?
maxRec.Height - rec.Height : rec.Top;
Bounds = new Rectangle(posLeft, posTop, rec.Width, rec.Height);
WindowState =
(FormWindowState)rt.Load(Name + "State",
(int)FormWindowState.Normal);
} // using
} // if (m_RegPath.Length)
} // LoadSettings()
}

// === helper classes for registry access:

public class RegTools : IDisposable
{
#region IDisposable Members
public void Dispose()
{
Deinit();
} // Dispose()
#endregion

private RegistryKey m_Key;

public RegTools() : this(null, false) {}
public RegTools(string rootKey) : this(rootKey, false) {}

public RegTools(string rootKey, bool isGlobal)
{
Deinit();
RegistryKey root = (isGlobal) ?
Registry.LocalMachine : Registry.CurrentUser;
if (string.IsNullOrEmpty(rootKey))
{
rootKey = string.Format(@"Software\{0}\{1}\",
Application.CompanyName, Application.ProductName);
} // if (rootKey)
m_Key = root.CreateSubKey(rootKey);
} // RegTools(rootKey, isGlobal)

private void Deinit()
{
if (m_Key != null)
{
m_Key.Close();
m_Key = null;
} // if (m_Key)
} // Deinit()

public string Load(string key, string defaultValue)
{
string result = defaultValue;
if (m_Key != null)
{
result = (string)m_Key.GetValue(key, defaultValue);
} // if (m_Key)
return (result);
} // Load(key, defaultValue)

public int Load(string key, int defaultValue)
{
int result = defaultValue;
if (m_Key != null)
{
result = (int)m_Key.GetValue(key, defaultValue);
} // if (m_Key)
return (result);
} // Load(key, defaultValue)

public bool Load(string key, bool defaultValue)
{
bool result = defaultValue;
if (m_Key != null)
{
result = (int)m_Key.GetValue(key, (defaultValue) ? 1 : 0) == 1;
} // if (m_Key)
return (result);
} // Load(key, defaultValue)

public Rectangle Load(string key, Rectangle defaultValue)
{
Rectangle result = defaultValue;
if (m_Key != null)
{
object obj;
obj = m_Key.GetValue(key);
if (obj != null)
{
string rect = obj.ToString();
string[] coord = rect.Split('|');
if (coord.Length == 4)
{
result = new Rectangle(
Int32.Parse(coord[0]),
Int32.Parse(coord[1]),
Int32.Parse(coord[2]),
Int32.Parse(coord[3]));
} // if (coord.Length)
} // if (obj)
} // if (m_Key)
return (result);
} // Load(key, defaultValue)

public void Save(string key, string value)
{
if (m_Key != null)
{
m_Key.SetValue(key,
value ?? string.Empty, RegistryValueKind.String);
} // if (m_Key)
} // Save(key, value)

public void Save(string key, int value)
{
if (m_Key != null)
{
m_Key.SetValue(key, value, RegistryValueKind.DWord);
} // if (m_Key)
} // Save(key, value)

public void Save(string key, bool value)
{
if (m_Key != null)
{
m_Key.SetValue(key, (value) ? 1 : 0, RegistryValueKind.DWord);
} // if (m_Key)
} // Save(key, value)

public void Save(string key, Rectangle value)
{
if (m_Key != null)
{
string bounds = string.Format("{0}|{1}|{2}|{3}",
value.X, value.Y, value.Width, value.Height);
m_Key.SetValue(key, bounds, RegistryValueKind.String);
} // if (m_Key)
} // Save(key, value)
} // class RegTools



Cheers,
Udo
 
L

Larry Smith

To be user-friendly, I like to store the size and position of a window so
that it can be opened in the same place the next time the user starts the
app. Ideally, I would simply retrieve this information during the
FormClosing event, but if the window is minimized at the time you get the
minimized size and not the "restored" size. (The one thing I don't want to
do is start the app minimized; it either opens at its last restored size
or maximized.) Because of this I record the form's position and size
during every Move or Resize event, but that seems clunky. Is there any way
to ask (.NET framework method or API call, I don't care) a minimized
window what its restored size and position are?

The following is by a very experienced MSFT developer (I've dealt with him
on other issues as well). Make sure you read some of the caveats in the
follow-up comments however.

http://blogs.msdn.com/rprabhu/archive/2005/11/28/497792.aspx
 
J

Jeff Johnson

Okay, RestoreBounds is a great property. But now I have a trickier question:
when a form is minimized, is there any way to tell if restoring it (i.e.,
right-clicking the taskbar button and selecting Restore) will return the
form to FormWindowState.Normal vs. FormWindowState.Maximized? In other
words, is there any way to tell what the form's last visible state was? (I
consider minimized forms to be "invisible" in the sense that they only
appear on the task bar.)
 
J

Jeff Johnson

Okay, RestoreBounds is a great property. But now I have a trickier
question: when a form is minimized, is there any way to tell if restoring
it (i.e., right-clicking the taskbar button and selecting Restore) will
return the form to FormWindowState.Normal vs. FormWindowState.Maximized?
In other words, is there any way to tell what the form's last visible
state was? (I consider minimized forms to be "invisible" in the sense that
they only appear on the task bar.)

Let me shoot down a potential solution before anyone makes it. I know I
could compare RestoreBounds against the available size of the screen (the
working area, specifically) and, if they're equal (or rather offset by the
sizing border width), assume the form is maximized, but theoretically a user
could resize a form to be that exact size, and it wouldn't REALLY be
maximized. I want to know for sure.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top