Click here to Skip to main content
14,973,807 members
Articles / Programming Languages / C#
Article
Posted 5 Sep 2008

Stats

38.2K views
178 downloads
25 bookmarked

Retain the size and position of forms and dialogs

Rate me:
Please Sign up or sign in to vote.
4.25/5 (9 votes)
5 Sep 2008CPOL2 min read
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.

C#
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.

C#
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.

C#
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.

C#
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.

C#
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)

Share

About the Author

Mycroft Holmes
Retired None
Australia Australia
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.

Comments and Discussions

 
QuestionThanks for the article... one suggestion Pin
Tom Clement10-Sep-13 8:19
professionalTom Clement10-Sep-13 8:19 
AnswerRe: Thanks for the article... one suggestion Pin
Mycroft Holmes10-Sep-13 12:44
professionalMycroft Holmes10-Sep-13 12:44 
GeneralRe: Thanks for the article... one suggestion Pin
Tom Clement10-Sep-13 13:17
professionalTom Clement10-Sep-13 13:17 
GeneralMy vote of 5 Pin
Support_Team23-Nov-10 22:11
MemberSupport_Team23-Nov-10 22:11 
GeneralGreat work, some mirror thing need to be changed Pin
Diing20-Jun-09 6:17
MemberDiing20-Jun-09 6:17 
GeneralRe: Great work, some mirror thing need to be changed Pin
Mycroft Holmes20-Jun-09 12:32
professionalMycroft Holmes20-Jun-09 12:32 
GeneralRe: Great work, some mirror thing need to be changed Pin
Diing21-Jun-09 20:55
MemberDiing21-Jun-09 20:55 
GeneralMy vote of 1 Pin
AndrewSmith2-Jan-09 14:39
MemberAndrewSmith2-Jan-09 14:39 
GeneralRe: My vote of 1 [modified] Pin
Mycroft Holmes6-Jan-09 14:12
professionalMycroft Holmes6-Jan-09 14:12 
GeneralGreat Article Pin
outdarkman22-Sep-08 6:36
Memberoutdarkman22-Sep-08 6:36 
GeneralRe: Great Article Pin
Diing20-Jun-09 5:08
MemberDiing20-Jun-09 5:08 
GeneralUser Settings Pin
Björn Friedrich11-Sep-08 4:01
MemberBjörn Friedrich11-Sep-08 4:01 
GeneralRe: User Settings Pin
Mycroft Holmes11-Sep-08 12:36
professionalMycroft Holmes11-Sep-08 12:36 
GeneralThis is good one Pin
Abhishek Sur8-Sep-08 20:59
professionalAbhishek Sur8-Sep-08 20:59 
GeneralRe: This is good one Pin
Mycroft Holmes9-Sep-08 22:50
professionalMycroft Holmes9-Sep-08 22:50 

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

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