Click here to Skip to main content
15,867,330 members
Articles / Desktop Programming / Windows Forms
Article

Windows Forms - Creating and Loading the Main Window Form and Child Control States Using C#

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
8 Dec 2008CPOL8 min read 40.8K   738   44   4
This article provides a simple example of how to save your application's main form and some of the related child control settings programmatically by subclassing an instance of the ApplicationSettingsBase class found in the .NET System.Configuration namespace.

Sample Application ScreenShot

Introduction

When developing a Windows based application, we strive to provide a high level of usability. One of the simplest and most effective ways to ensure a high level of usability in a .NET Windows Forms based application is to save the main window size and position, along with the state of its related child controls. By saving the state of the main form and any related child controls, the user can pick up and resume using the application where they left off, the next time they need to run the same application.

This article provides an example of how to save your application's main form and some of the related child control settings programmatically by subclassing an instance of the ApplicationSettingsBase class found in the .NET System.Configuration namespace. To illustrate how you can develop and integrate your own subclass of the ApplicationSettingsBase class, I've provided a simple Windows Forms based application, SimplePersistentFormCS, that allows you to type in any text string and modify the font and word wrap settings within the main form's TextBox. As the application loads and runs, it attempts to set the main form to the same settings as used in the previous session for running the application.

The sample application's ApplicationSettingsBase subclass, MainFormSettings, will save or persist the following settings each time the user exits the application:

  • The Location or the position of the main form inside the main desktop window. If the previous session's location for the main application window is not available, the MainFormSettings class will automatically center the form when loaded.
  • The Size, or width and height of the Main application Window.
  • The Font, its point size, and style when displaying or modifying text inside the main form's TextBox.

Background

ApplicationSettingsBase saves the main form and other application settings that you define as read-write properties in your application's own subclass in an XML based file, named user.config. By default, the user.config is saved on a per Windows user basis in an application specific subdirectory under the Local Settings\Application Data directory path referenced in the USERPROFILE Windows environment variable. To determine the actual application settings specific subdirectory that will contain the user.config file, the .NET Framework's backing implementation of the ApplicationSettingsBase class will check the following set of properties defined in your application's assembly at runtime:

Image 2

Using the Code

MainFormSettings.cs

MainFormSettings is the subclass of ApplicationSettingsBase that contains the four main application window settings that we'll save between runs: the Location and Size of the form, the Font for displaying text within the Windows.Forms.TextBox control, and WordWrap, a boolean value indicating if each line in the TextBox will be automatically wrapped.

C#
using System;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace SimplePersistentFormCS
{
    class MainFormSettings : ApplicationSettingsBase
    {
        [UserScopedSetting()]
        public Point Location
        {
            get
            {
                if (this["Location"] == null)
                {
                    Size mainFormSize = this.Size;

                    int startingXPos = 
                    ((int)(Screen.PrimaryScreen.Bounds.Width / 2)) - 
                    ((int)(mainFormSize.Width / 2));

                    int startingYPos = 
                    ((int)(Screen.PrimaryScreen.Bounds.Height / 2)) - 
                    ((int)(mainFormSize.Height / 2));

                    this["Location"] = 
                    new Point(startingXPos, startingYPos);

                    return (Point)this["Location"];
                }

                else
                {
                    return (Point) this["Location"];
                }
            }

            set
            {
                this["Location"] = (Point)value;
            }
        }

        [UserScopedSetting()]
        [DefaultSettingValueAttribute("480, 360")]
        public Size Size
        {
            get
            {
                return (Size)this["Size"];
            }

            set
            {
                this["Size"] = (Size)value;
            }
        }

        [UserScopedSetting()]
        [DefaultSettingValueAttribute("Courier New, 11pt")]
        public Font Font
        {
            get
            {
                return (Font)this["Font"];
            }

            set
            {
                this["Font"] = (Font)value;
            }
        }

        [UserScopedSetting()]
        [DefaultSettingValueAttribute("false")]
        public bool WordWrapEnabled
        {
            get
            {
                return (bool)this["WordWrapEnabled"];
            }

            set
            {
                this["WordWrapEnabled"] = (bool) value;
            }
        }
    }
}
MainFormSettings.cs - An ApplicationsSettingsBase subclass.

Each of the four properties saved between user sessions of running the application are declared as instances of the UserScopedSetting attribute class, which will be added to the <userSettings> section of the user.config XML file. Along with the UserScopedSetting attribute, we can also specify a default value for a property that will be used if the user.config file cannot be accessed or doesn't exist, as in running the application for the first time. The default user setting values are defined using the DefaultSettingValueAttribute class. For example, with the MainFormSettings.<code>WordWrapEnabled property, word wrapping in the application's MainEditTextBox control is disabled, by default:

C#
[UserScopedSetting()]
[DefaultSettingValueAttribute("false")]
public bool WordWrapEnabled
{
    get
    {
        return (bool)this["WordWrapEnabled"];
    }

    set
    {
        this["WordWrapEnabled"] = (bool) value;
    }
}
The MainFormSettings.WordWrapEnabled property - By default, word wrapping in the sample application is disabled.

The ApplicationSettingsBase class serializes the WordWrapEnabled property as a string, and adds the property in its own XML <setting> element in the <userSettings> section of the user.config file:

XML
<userSettings>
    <SimplePersistentFormCS.MainFormSettings>
       <!-- Additional Size & Location properties omitted here for clarity. -->
        <setting name="WordWrapEnabled" serializeAs="String">
            <value>True</value>
        </setting>
        <!-- Additional Font property omitted here for clarity. -->
    </SimplePersistentFormCS.MainFormSettings>
</userSettings>
The MainFormSettings.WordWrapEnabled property as it is formatted and saved in the XML based user.config file.

Of the four application properties defined in the MainFormSettings class, two additional properties have default values defined in a similar manner: Size and Font. Like the WordWrap property, the System.Drawing instance values for both Size and Font are serialized and added to the user.config XML file as strings.

Location Property and Centering the Main Application Form by Default

Since the screen resolution and the number of monitors the PC may have configured for running applications can differ from system to system, the Location property in the MainFormSettings class does not provide a default System.Drawing.Point value. Instead, the Location property get accessor checks for a null reference to a Point value structure. If the Point is a null reference, as it will be the first time you run the sample application on a PC that doesn't have a user.config file for the current Windows user, the get method section will determine the vertical and horizontal center of the primary display at which to open the application's main form based on its Size property.

C#
[UserScopedSetting()]
public Point Location
{
    get
    {
        if (this["Location"] == null)
        {
            Size mainFormSize = this.Size;

            int startingXPos = 
            ((int)(Screen.PrimaryScreen.Bounds.Width / 2)) - 
            ((int)(mainFormSize.Width / 2));

            int startingYPos = 
            ((int)(Screen.PrimaryScreen.Bounds.Height / 2)) - 
            ((int)(mainFormSize.Height / 2));

            this["Location"] = 
            new Point(startingXPos, startingYPos);

            return (Point)this["Location"];
        }

        else
        {
            return (Point) this["Location"];
        }
    }

    set
    {
        this["Location"] = (Point)value;
    }
}
Initializing the default main form Location property to center the form in the primary display based on its default size.

In order to determine the center of the main application form from within the Location property accessor, we must know what the current or default size of the form is. We can access the Size property value, either the default or the current Size, by using the this reference to our same instance of the MainFormSettings class, as in:

C#
if (this["Location"] == null)
{
    // Accessing the default Size property value within the same
    // MainFormSettings class...
    Size mainFormSize = this.Size;

In order to ensure that the MainForm class will load and position itself at the correct startup location, the Windows.Forms.Form StartPosition property must be changed from its default value of WindowsDefaultLocation to Manual. This will allow us to load and use the MainFormsSetting.Location property to automatically center the main application window for the first time, or restore it to its last position from a previous user session.

MainForm StartPosition In IDE

Modifying the MainForm.StartPosition property using the Visual Studio Designer to allow the application code to set its starting position programmatically.

Accessing MainFormSettings from Within the Application

Loading the Settings

The main application window for the sample application, MainForm, contains a single private data member, _theSettings, which is an instance of the ApplicationSettingsBase subclass, MainFormSettings. The MainFormSettings class can be instantiated in either the MainForm constructor or in the MainForm Load event handler, or in any other member function, as long as it's instantiated before it's used. For simplicity and to keep the sample code concise, I've added the instantiation of the MainFormSettings class in the MainForm Load event handler, MainForm_Load().

C#
private void MainForm_Load(object sender, EventArgs e)
{
    _theSettings = new MainFormSettings();

    this.Size = _theSettings.Size;
    this.Location = _theSettings.Location;

    MainEditTextBox.Font = _theSettings.Font;
    MainEditTextBox.WordWrap = _theSettings.WordWrapEnabled;

    return;
}
The MainForm Load event handler: Instantiating and setting the application settings when the main application window is displayed for the first time.

If we don't check the current MainForm WindowState property to see if the main application window is minimized, the user would only be able to view the MainForm in its maximized state. Additionally, the Restore application window context menu item would only minimize the MainForm again and keep the form in its minimized state.

Regardless as to whether or not the MainForm is minimized, we can always safely save the MainEditTextBox's selected Font and WordWrap properties to our ApplicationSettingsBase subclassed object, _theSettings, and have the same basic display and layout of any text that is typed or pasted into the TextBox control as found when the application was last run.

Additional Note

This sample application works without any issues on dual screen system configurations, including when opening a previous session with the form's Location and Size properties as saved in the user.config file, as well as setting the initial position of the MainForm to the secondary display monitor.

Additional Resources

  • MSDN Online: Windows Forms Programming - Application Settings For Windows Forms

    The basis for this article on how I could initialize, save, and restore an application’s state is in the article How to: Create Application Settings, which can be found here. If you are working in .NET 3.0 or .NET 2.0 with Visual Studio 2005, you may want to review the quick links provided by MSDN for your specific development platform.

  • Windows Forms 2.0 Programming Sells, Chris Sells, Weinhardt, Michael (2006: Addison-Wesley, ISBN-10 0321267966, ISBN-13 9780321267962, 988 pages)

    This book is perhaps one of the few .NET development books I would consider as "a must have" on your bookshelf. Of special interest in working with the .NET Framework support for persisting application and user settings can be found in Chapter 15, entitled Settings. The Settings chapter provides the most extensive overview and information on working with Application Settings, User Settings, and Roaming-User Settings, in addition to working with the Settings Designer tools inside Visual Studio.

  • The Code Project: Windows Forms - Creating and Persisting Custom User Settings in C# Gennaro, Frank (2487219)

    In this article, Frank provides a great overview on how you can easily support serialization of custom objects to an ApplicationSettingsBase subclass, beginning with the Windows Forms Project Properties Settings Designer, and then follows through with a quick sample on how to save and load a System.Collections.Generic.SortedList containing a custom object. If my article was of value to you as to how you can improve your application's overall level of usability, then Frank's article should be the next article on your reading list.

History

  • 08-Dec-08: Original article submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey19-Feb-12 21:50
professionalManoj Kumar Choubey19-Feb-12 21:50 
GeneralAlternative solution to persist control and form settings Pin
Jani Giannoudis9-Dec-08 3:46
Jani Giannoudis9-Dec-08 3:46 
Generalone question Pin
Seraph_summer8-Dec-08 23:39
Seraph_summer8-Dec-08 23:39 
GeneralRe: one question Pin
ClockEndGooner14-Dec-08 12:59
ClockEndGooner14-Dec-08 12:59 

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.