Click here to Skip to main content
Licence CPOL
First Posted 5 Sep 2008
Views 16,308
Downloads 59
Bookmarked 25 times

Retain the size and position of forms and dialogs

By | 5 Sep 2008 | Article
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mycroft Holmes

Software Developer (Senior)
Contractor
Singapore Singapore

Member

Started my programming life writing Excel 1.0 macros, God what a long time ago.
 
Now I'm a dotnet developer, I get to influence direction, play with new toys, build stuff, life is wonderful.
 
Greatest buzz you can get, walk past a row of desks and see your application running on all of them (and getting paid).
 
Greatest irritant, pouring 12 months of knowledge and experience into an empty head only to have it leave.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 PinmemberSupport_Team22:11 23 Nov '10  
GeneralGreat work, some mirror thing need to be changed PinmemberDiing6:17 20 Jun '09  
GeneralRe: Great work, some mirror thing need to be changed PinmemberMycroft Holmes12:32 20 Jun '09  
GeneralRe: Great work, some mirror thing need to be changed PinmemberDiing20:55 21 Jun '09  
GeneralMessage Automatically Removed PinmemberAndrewSmith14:39 2 Jan '09  
GeneralRe: My vote of 1 [modified] PinmemberMycroft Holmes14:12 6 Jan '09  
GeneralGreat Article Pinmemberoutdarkman6:36 22 Sep '08  
GeneralRe: Great Article PinmemberDiing5:08 20 Jun '09  
GeneralUser Settings PinmemberChantiPDM4:01 11 Sep '08  
GeneralRe: User Settings PinmemberMycroft Holmes12:36 11 Sep '08  
GeneralThis is good one PinmemberAbhishek sur20:59 8 Sep '08  
GeneralRe: This is good one PinmemberMycroft Holmes22:50 9 Sep '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 5 Sep 2008
Article Copyright 2008 by Mycroft Holmes
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid