Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Retain the size and position of forms and dialogs

0.00/5 (No votes)
5 Sep 2008 1  
Store and retreives the last position and size of a form using an XML file.

Demo

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 //create the table
            {
                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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here