Introduction
While converting my VB utilities, I decided this was a small, atomic bit of code that may be useful to a newbie. This belongs in my UI utilities class which is included in all my WinForms apps. It stores the position and size of the form in an XML table in the application data folder for the user.
Background
I hate setting up a form to meet my requirements only to have it reset to the default every time I open it. Take a look at the event viewer; here, you are with a monster screen set at 1280*1024 minimum, and this dinky little window opens that would be perfect on 640*480. This simple code solves that problem.
Using the code
FormStateRead()
This method reads the XML file into a datatable. If there is no existing file, it creates the datatable.
internal static DataTable FormStateRead()
{
try
{
if (dtFormState == null)
{
DataTable dtData;
string sFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string sFile = Path.Combine(sFolder, "FormState.xml");
FileInfo oFI = new FileInfo(sFile);
if (oFI.Exists)
{
DataSet dsData = new DataSet();
dsData.ReadXml(sFile);
dtData = dsData.Tables[0];
}
else
{
dtData = new DataTable();
dtData.Columns.Add("Application",
System.Type.GetType("System.String"));
dtData.Columns.Add("FormName",
System.Type.GetType("System.String"));
dtData.Columns.Add("State",
System.Type.GetType("System.Int32"));
dtData.Columns.Add("Left",
System.Type.GetType("System.Int32"));
dtData.Columns.Add("Top",
System.Type.GetType("System.Int32"));
dtData.Columns.Add("Width",
System.Type.GetType("System.Int32"));
dtData.Columns.Add("Height",
System.Type.GetType("System.Int32"));
}
dtFormState = dtData;
}
return dtFormState;
}
catch (Exception) { throw; }
}
FormStateSet()
This is the entry point passing in the current form from the form load event. It searches the datatable to locate the form name. If there are no records, a new record is created and populated with the current form's details.
internal static void FormStateSet(Form oForm)
{
try
{
StringBuilder sFilter = new StringBuilder();
sFilter.AppendFormat("FormName = '{0}'", oForm.Name);
if (dtFormState == null)
{
FormStateRead();
}
DataRow[] dtRows = dtFormState.Select(sFilter.ToString());
if (dtRows.Length == 1)
{
oForm.WindowState = (System.Windows.Forms.FormWindowState)
Convert.ToInt32((string)dtRows[0]["State"]);
if (oForm.WindowState == FormWindowState.Normal)
{
oForm.SetDesktopBounds(Convert.ToInt32((string)dtRows[0]["Left"]),
Convert.ToInt32((string)dtRows[0]["Top"]),
Convert.ToInt32((string)dtRows[0]["Width"]),
Convert.ToInt32((string)dtRows[0]["Height"]));
}
}
else
{
DataRow drData = dtFormState.NewRow();
drData["Application"] = GetAppName();
drData["FormName"] = oForm.Name;
drData["State"] = (int)oForm.WindowState;
drData["Left"] = oForm.Left;
drData["Top"] = oForm.Top;
drData["Width"] = oForm.Width;
drData["Height"] = oForm.Height;
dtFormState.Rows.Add(drData);
}
}
catch (Exception) { throw; }
}
This needs to be called from the constructor, directly after the InitializeComponent()
. If it is called in the form open event. There is a horrible Flash as the form moves from the default to the form state position.
FormStateSave(Form oForm)
This is called from the FormClosing
event, and stores the last position and size for the form into the datatable and writes the XML file to disk.
internal static void FormStateSave(Form oForm)
{
try
{
StringBuilder sFilter = new StringBuilder();
sFilter.AppendFormat("FormName = '{0}'", oForm.Name);
DataRow[] drRows = dtFormState.Select(sFilter.ToString());
DataRow drData;
if (drRows.Length == 0)
{
drData = dtFormState.NewRow();
dtFormState.Rows.Add(drData);
}
drData = drRows[0];
drData["Application"] = GetAppName();
drData["FormName"] = oForm.Name;
drData["State"] = (int)oForm.WindowState;
drData["Left"] = oForm.Left;
drData["Top"] = oForm.Top;
drData["Width"] = oForm.Width;
drData["Height"] = oForm.Height;
FormStateWrite();
}
catch (Exception) { throw; }
}
FormStateWrite()
This private method writes the datatable to the XML file.
private static void FormStateWrite()
{
try
{
string sFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string sFile = Path.Combine(sFolder, "FormState.xml");
dtFormState.WriteXml(sFile);
}
catch (Exception) { throw; }
}
FormStateReset()
And, of course, you must be able to reset all the forms to the default.
internal static void FormStateReset()
{
try
{
for (int i = dtFormState.Rows.Count - 1; i > -1; i--)
{
if ((string)dtFormState.Rows[i]["Application"] == GetAppName())
{
dtFormState.Rows[i].Delete();
}
}
dtFormState.AcceptChanges();
if (dtFormState.Rows.Count == 0)
{
string sFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string sFile = Path.Combine(sFolder, "FormState.xml");
FileInfo oFI = new FileInfo(sFile);
if (oFI.Exists)
{
oFI.Delete();
}
dtFormState = null;
}
else
{
FormStateWrite();
}
}
catch (Exception) { throw; }
}
Points of interest
Note: the form's open position needs to be set to manual.
History
First draft.