Click here to Skip to main content
15,886,199 members
Articles / Programming Languages / C#
Article

Form and Control Position and Size Utility

Rate me:
Please Sign up or sign in to vote.
3.38/5 (9 votes)
4 Apr 2003 68.6K   505   29   6
Allows easy saving and loading of form and control's position and size.

Sample Image - positiondemo.png

Introduction

I find it really annoying having to constantly reposition and size certain windows the way I like them in some of the application I use regularly. This code allows easy saving and loading of forms and controls positioning and size, making your WinForm application more user friendly.

Using the code

To load the data, place code after InitializeComponent() in the Form's constructor.

C#
public Form1(){

    InitializeComponent();

    // load positioning and size
    McGiv.Win32.Forms.Positioning.Load(this, 
              RegistryHive.CurrentUser, "regSubKey");
            
    // any other controls ie
    // McGiv.Win32.Forms.Positioning.Load(this.ControlName, 
    //                RegistryHive.CurrentUser, "regSubKey");

}

To save the data, place code in OnClosing method of the Form.

C#
protected override void OnClosing( System.ComponentModel.CancelEventArgs e){

    // save position and size
    McGiv.Win32.Forms.Positioning.Save(this, 
                  RegistryHive.CurrentUser, "regSubKey");
    
    // any other controls ie
    //McGiv.Win32.Forms.Positioning.Save(this.ControlName, 
    //                   RegistryHive.CurrentUser, "regSubKey");

}

The whole code listing:

using System;
using Microsoft.Win32;
using System.Windows.Forms; 
                             

namespace McGiv.Win32.Forms {


    /// <summary>
    /// Allows the easy loading and saving of control position and size.
    /// Also saves and loads the window position of forms.
    /// </summary>
    internal class Positioning {
   
        /// <summary>
        /// Saves the position and size of the given control.
        /// If control is a Form object it saves its window position.
        /// Best placed in the OnClosing method of the (parent) Form.
        /// </summary>
        /// <param name="control">The control to be saved</param>
        /// <param name="topLevel">Registry top level key.</param>
        /// <param name="subKey">The sub key that 
        ///              the data is saved to.</param>
        public static void Save(Control control, 
                   RegistryHive topLevel, string subKey){
            // todo validate subKey
            if( control == null )
            {
                throw new ArgumentException("The control cannot be null");
            }

            // open key
            Microsoft.Win32.RegistryKey key =  Open(topLevel, subKey);

            // form state
            Form form = control as Form;
            if( form != null ){
                key.SetValue(form.Name + "_windowState", (int)form.WindowState);

                // if window is not in normal mode set to normal before saving
                if( form.WindowState != FormWindowState.Normal ){
                    // save normal windo size
                    form.WindowState = FormWindowState.Normal;
                }
            }

            // save screen res
            key.SetValue(control.Name + "_screenHeight", 
                          Screen.PrimaryScreen.Bounds.Height); 
            key.SetValue(control.Name + "_screenWidth", 
                           Screen.PrimaryScreen.Bounds.Width);

            // control position/size
            key.SetValue(control.Name + "_top", control.Top);
            key.SetValue(control.Name + "_left", control.Left);
            key.SetValue(control.Name + "_width", control.Width);
            key.SetValue(control.Name + "_height", control.Height);

            // close key after use
            key.Close();
        }

        /// <summary>
        /// Loads the position and size of a control.
        /// If control is a form also loads the window position.
        /// Best placed in the Form's constructor.
        /// </summary>
        /// <param name="control">The control to be loaded.</param>
        /// <param name="topLevel">Registry top level key.</param>
        /// <param name="subKey">The sub key where the data is saved.</param>
        public static void Load(Control control, 
                    RegistryHive topLevel, string subKey){

            // todo validate subKey

            if( control == null ){
                throw new ArgumentException("The control cannot be null");
            }

            // open key
            Microsoft.Win32.RegistryKey key = Open(topLevel, subKey);

            // check that screen res is the same
            // if not or can't be found revert to origional.
            try{
                if(Screen.PrimaryScreen.Bounds.Height != 
                   (int)key.GetValue(control.Name + "_screenHeight") || 
                   Screen.PrimaryScreen.Bounds.Width != 
                   (int)key.GetValue(control.Name + "_screenWidth") ){

                    return;
                }
            }
            catch(NullReferenceException){return;}

            control.SuspendLayout();

            // form state
            Form form = control as Form;
            if( form != null ){
                try{
                    form.WindowState = 
                      (FormWindowState)key.GetValue(form.Name + 
                      "_windowState");
                    form.StartPosition = FormStartPosition.Manual;
                }
                catch(NullReferenceException){}
            }

            // control position/size
            try{
                control.Top = (int)key.GetValue(control.Name + "_top");
            }
            catch(NullReferenceException){}
            try{
                control.Left = (int)key.GetValue(control.Name + "_left");
            }
            catch(NullReferenceException){}
            try{
                control.Width = (int)key.GetValue(control.Name + "_width");
            }
            catch(NullReferenceException){}
            try{
                control.Height = (int)key.GetValue(control.Name + "_height");
            }
            catch(NullReferenceException){}

            control.ResumeLayout();

            // close key after use
            key.Close();

        }

        /// <summary>
        /// Opens a Registry key with write access.
        /// If the key dosn't exist it creates one.
        /// </summary>
        /// <param name="topLevel">Registry top level key.</param>
        /// <param name="subKey">Subkey to be opened.</param>
        /// <returns>Writable registry key</returns>
        private static Microsoft.Win32.RegistryKey 
                Open(RegistryHive topLevel, string subKey){

            switch( topLevel){

                case RegistryHive.ClassesRoot:{

                    return Registry.CurrentUser.CreateSubKey(subKey);
                }
                case RegistryHive.CurrentConfig:{

                    return Registry.CurrentConfig.CreateSubKey(subKey);
                }
                case RegistryHive.CurrentUser:{

                    return Registry.CurrentUser.CreateSubKey(subKey);
                }
                case RegistryHive.DynData:{

                    return Registry.DynData.CreateSubKey(subKey);
                }
                case RegistryHive.LocalMachine:{

                    return Registry.LocalMachine.CreateSubKey(subKey);
                }
                case RegistryHive.PerformanceData:{

                    return Registry.PerformanceData.CreateSubKey(subKey);
                }
                case RegistryHive.Users:{

                    return Registry.Users.CreateSubKey(subKey);
                }
                default:{

                    return null;
                }

            }
        }

    }
}

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


Written By
Web Developer
United Kingdom United Kingdom
I'm a 3rd year student at Uni studing Computing. I've been coding in VB for about 6 years, Java for about 3 and C# for about 2 years.

Comments and Discussions

 
GeneralCool code Pin
Carl Mercier7-Apr-03 11:26
Carl Mercier7-Apr-03 11:26 
Questionhow about correct dave of form position? Pin
Oleksandr Kucherenko7-Apr-03 5:47
Oleksandr Kucherenko7-Apr-03 5:47 
try to do such things:
1. ( start application ) open form
2. resize a form and change it position
3. maximize form
4. close form

5. start application
6. return form to normal window state

Result:
- position and size of form not stored correctly

Also saving of form settings does not take care about Workspace resolution change:
start application in 1024x786
and start application in 640x480

postion and size of form may be incorrect for small resolution!!!!

solution:
part of my code which used for form state serialization
regSerialization_RecoverSettings method called when form load itself
and
regSerialization_SaveSettings method called when form closed

<br />
    protected virtual void regSerialization_RecoverSettings( object sender, SerializationEventArgs data )<br />
    {<br />
      if( !this.IsHandleCreated ) return;<br />
<br />
      Rectangle rc = SystemInformation.WorkingArea;<br />
<br />
      // recover size<br />
      if( SerializeSize && CanSaveSize )<br />
      {<br />
        int iWidth = data[ SerializeSubKey ].GetIntValue( "Width", this.Width );<br />
        int iHeight= data[ SerializeSubKey ].GetIntValue( "Height", this.Height );<br />
<br />
        /// prevent restoring of form size from settings when workspace <br />
        /// resolution is too small for resized form<br />
        if( rc.Width >= iWidth )<br />
        {<br />
          this.Width = iWidth;<br />
        }<br />
<br />
        if( rc.Height >= iHeight )<br />
        {<br />
          this.Height = iHeight;<br />
        }<br />
      }<br />
<br />
      // recover position<br />
      if( SerializePosition )<br />
      {<br />
        int iLeft = data[ SerializeSubKey ].GetIntValue( "Left", this.Left );<br />
        int iTop  = data[ SerializeSubKey ].GetIntValue( "Top", this.Top );<br />
<br />
        /// Restore form position only in case when workspace<br />
        /// resolution is large enough for displaing a part of form<br />
        if( iLeft >= 0 && iLeft < rc.Width )<br />
        {<br />
          this.Left = iLeft;<br />
        }<br />
<br />
        if( iTop >= 0 && iTop < rc.Height )<br />
        {<br />
          this.Top = iTop;<br />
        }<br />
      }<br />
      <br />
      if( SerializeWindowState && CanSaveState )<br />
      {<br />
        string output = data[ SerializeSubKey ].GetStringValue( "WindowState", this.WindowState.ToString() );<br />
        FormWindowState state = ( FormWindowState )Enum.Parse( typeof( FormWindowState ), output, true );<br />
        this.WindowState = state;<br />
      }<br />
    }<br />
<br />
    protected virtual void regSerialization_SaveSettings( object sender, SerializationEventArgs data )<br />
    {<br />
      if( !this.IsHandleCreated ) return;<br />
<br />
      if( SerializeWindowState && CanSaveState )<br />
      {<br />
        FormWindowState state = this.WindowState;<br />
        <br />
        // do not save minimized state - replace minimize state to Normal <br />
        if( state == FormWindowState.Minimized )<br />
          state = FormWindowState.Normal;<br />
<br />
        data[ SerializeSubKey ].AddValue( "WindowState", state.ToString() );<br />
      }<br />
<br />
      // save window size and position of window in normal state<br />
      WINDOWPLACEMENT place = new WINDOWPLACEMENT();<br />
      place.length = (uint)Marshal.SizeOf( typeof( WINDOWPLACEMENT ) );<br />
      <br />
      WindowsAPI.GetWindowPlacement( this.Handle, ref place );<br />
      Rectangle rc = ( Rectangle )place.rcNormalPosition;<br />
<br />
      // save size<br />
      if( SerializeSize && CanSaveSize )<br />
      {<br />
        data[ SerializeSubKey ].AddValue( "Width", rc.Width );<br />
        data[ SerializeSubKey ].AddValue( "Height", rc.Height );<br />
      }<br />
<br />
      // save position<br />
      if( SerializePosition )<br />
      {<br />
        data[ SerializeSubKey ].AddValue( "Left", rc.Left );<br />
        data[ SerializeSubKey ].AddValue( "Top", rc.Top );<br />
      }<br />
    }<br />


Good Luck
Alex Kucherenko
AnswerUpdated Code Pin
McGiv7-Apr-03 6:17
McGiv7-Apr-03 6:17 
GeneralFormatting Messed Up Pin
BarryJ5-Apr-03 19:04
BarryJ5-Apr-03 19:04 
GeneralRe: Formatting Messed Up Pin
McGiv5-Apr-03 23:32
McGiv5-Apr-03 23:32 
GeneralRe: Formatting Messed Up Pin
BarryJ6-Apr-03 7:10
BarryJ6-Apr-03 7:10 

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.