Click here to Skip to main content
15,885,757 members
Articles / Programming Languages / C#

Zeta .NET Base Libraries

Rate me:
Please Sign up or sign in to vote.
4.41/5 (44 votes)
30 Mar 2007CPOL3 min read 151.5K   2.4K   147  
A small set of general-purpose classes for using in .NET applications
namespace ZetaLib.Windows.Common
{
	#region Using directives.
	// ----------------------------------------------------------------------

	using System;
	using System.Diagnostics;
	using System.Windows.Forms;
	using ZetaLib.Core.Common;
	using ZetaLib.Core.Collections;
	using System.Collections.Generic;
	using ZetaLib.Windows.Properties;
	using System.Runtime.Serialization;
	using ZetaLib.Core.Logging;
	using ZetaLib.Core.Localization;
	using System.Drawing;

	// ----------------------------------------------------------------------
	#endregion

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// Class with helper routines for Windows Forms applicatins.
	/// </summary>
	public sealed class FormHelper
	{
		#region Saving window states and values.
		// ------------------------------------------------------------------

		/// <summary>
		/// Saves the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		public static void SaveState(
			Control c )
		{
			SaveState( Storage, c );
		}

		/// <summary>
		/// Saves the state of a control.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		public static void SaveState(
			IPersistentPairStorage storage,
			Control c )
		{
			string prefix = c.Name;

			SaveValue( storage, prefix + @".Left", c.Left );
			SaveValue( storage, prefix + @".Top", c.Top );
			SaveValue( storage, prefix + @".Width", c.Width );
			SaveValue( storage, prefix + @".Height", c.Height );

			if ( c is Splitter )
			{
				SaveValue(
					storage,
					prefix + @".SplitPosition",
					((Splitter)c).SplitPosition );
			}
			else if ( c is Form )
			{
				Form s = c as Form;
				SaveState( s );
			}
			else if ( c is SplitContainer )
			{
				SplitContainer s = c as SplitContainer;
				SaveState( s );
			}
			else if ( c is TabControl )
			{
				SaveValue(
					storage,
					prefix + @".SelectedIndex",
					((TabControl)c).SelectedIndex );
			}
			else if ( c is ListView )
			{
				ListView listView = c as ListView;

				SaveValue(
					storage,
					prefix + @".Columns.Count",
					listView.Columns.Count );

				for ( int i = 0; i < listView.Columns.Count; ++i )
				{
					SaveValue(
						storage,
						prefix + @".Columns." + (i + 1) + @".Width",
						listView.Columns[i].Width );
				}

				// --

				SaveValue(
					storage,
					prefix + @".SelectedIndexes.Count",
					listView.SelectedIndices.Count );

				for ( int i = 0; i < listView.SelectedIndices.Count; ++i )
				{
					SaveValue(
						storage,
						prefix + @".SelectedIndexes." + (i + 1) + @".Index",
						listView.SelectedIndices[i] );
				}
			}
			else if ( c is TextBox )
			{
				TextBox t = c as TextBox;

				SaveValue( storage, prefix + @".Text", t.Text );
			}
			else if ( c is CheckBox )
			{
				CheckBox cb = c as CheckBox;

				SaveValue(
					storage,
					prefix + @".CheckState",
					cb.CheckState.ToString() );
			}
			else if ( c is RadioButton )
			{
				RadioButton rb = c as RadioButton;

				SaveValue(
					storage,
					prefix + @".Checked",
					rb.Checked );
			}
			else if ( c is DateTimePicker )
			{
				DateTimePicker rb = c as DateTimePicker;

				SaveValue(
					storage,
					prefix + @".Value",
					rb.Value );
				SaveValue(
					storage,
					prefix + @".Checked",
					rb.Checked );
			}
			else if ( c is CheckedListBox )
			{
				CheckedListBox clb = c as CheckedListBox;

				List<int> selectedIndices = new List<int>();

				foreach ( int si in clb.CheckedIndices )
				{
					selectedIndices.Add( si );
				}

				string sis = StringHelper.SerializeToString(
					selectedIndices.ToArray() );

				SaveValue(
					storage,
					prefix + @".CheckedIndices",
					sis );
			}
			else if ( c is ComboBox )
			{
				ComboBox rb = c as ComboBox;

				SaveValue(
					storage,
					prefix + @".SelectedIndex", rb.SelectedIndex );

				if ( rb.DropDownStyle == ComboBoxStyle.DropDown )
				{
					SaveValue( storage, prefix + @".Text", rb.Text );
				}
			}
			else
			{
				Debug.Assert(
					false,
					string.Format(
					@"Trying to save the state of an unknown control type: '{0}'.",
					c.GetType() ) );
			}

			// --

			if ( c is ISaveRestoreState )
			{
				ISaveRestoreState srs = c as ISaveRestoreState;

				if ( !protectRecursion.Contains( srs ) )
				{
					protectRecursion.Add( srs );
					try
					{
						srs.OnSaveState( storage, prefix );
					}
					finally
					{
						protectRecursion.Remove( srs );
					}
				}
			}
		}

		/// <summary>
		/// Persist a name-value pair inside the registry.
		/// Does this on a per-user-basis.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="val">The val.</param>
		public static void SaveValue(
			string name,
			object val )
		{
			SaveValue( Storage, name, val );
		}

		/// <summary>
		/// Persist a name-value pair inside the registry.
		/// Does this on a per-user-basis.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <param name="val">The val.</param>
		public static void SaveValue(
			IPersistentPairStorage storage,
			string name,
			object val )
		{
			storage.PersistValue( name, val );
		}

		/// <summary>
		/// Persist a name-value pair inside the registry.
		/// Does this on a per-user-basis.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="val">The val.</param>
		public static void SerializeValue(
			string name,
			object val )
		{
			SerializeValue( storage, name, val );
		}

		/// <summary>
		/// Persist a name-value pair inside the registry.
		/// Does this on a per-user-basis.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <param name="val">The val.</param>
		public static void SerializeValue(
			IPersistentPairStorage storage,
			string name,
			object val )
		{
			if ( val == null )
			{
				SaveValue( storage, name, null );
			}
			else
			{
				SaveValue(
					storage,
					name,
					StringHelper.SerializeToString( val ) );
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Restoring window states and values.
		// ------------------------------------------------------------------

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		public static void RestoreState(
			Control c )
		{
			RestoreState( Storage, c, null );
		}

		/// <summary>
		/// Restores the state of a control.
		/// Works for list views, too (column widths).
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		public static void RestoreState(
			IPersistentPairStorage storage,
			Control c )
		{
			RestoreState( storage, c, null );
		}

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		/// <param name="info">The info.</param>
		public static void RestoreState(
			Control c,
			RestoreInformation info )
		{
			RestoreState( Storage, c, info );
		}

		/// <summary>
		/// Restores the state of a control.
		/// Works for list views, too (column widths).
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		/// <param name="info">The info.</param>
		public static void RestoreState(
			IPersistentPairStorage storage,
			Control c,
			RestoreInformation info )
		{
			string prefix = c.Name;

			object o = null;

			if ( c is Splitter )
			{
				o = RestoreValue( storage, prefix + @".SplitPosition" );
				if ( o != null )
				{
					((Splitter)c).SplitPosition = Convert.ToInt32( o );
				}
			}
			else if ( c is Form )
			{
				Form s = c as Form;
				RestoreState( storage, s, info );
			}
			else if ( c is SplitContainer )
			{
				SplitContainer s = c as SplitContainer;
				RestoreState( storage, s );
			}
			else if ( c is TabControl )
			{
				o = RestoreValue( storage, prefix + @".SelectedIndex" );
				if ( o != null )
				{
					((TabControl)c).SelectedIndex = Convert.ToInt32( o );
				}
			}
			else if ( c is ListView )
			{
				ListView listView = c as ListView;

				o = RestoreValue( storage, prefix + @".Columns.Count" );

				if ( o != null )
				{
					int count = Convert.ToInt32( o );
					for ( int i = 0; i < count; ++i )
					{
						o = RestoreValue( storage, prefix + @".Columns." + (i + 1) + @".Width" );

						if ( o != null && i < listView.Columns.Count )
						{
							listView.Columns[i].Width = Convert.ToInt32( o );
						}
					}
				}

				// --

				listView.SelectedItems.Clear();

				o = RestoreValue( storage, prefix + @".SelectedIndexes.Count" );

				if ( o != null )
				{
					int count = Convert.ToInt32( o );
					for ( int i = 0; i < count; ++i )
					{
						o = RestoreValue( storage, prefix + @".SelectedIndexes." + (i + 1) + @".Index" );

						if ( o != null )
						{
							int index = ConvertHelper.ToInt32( o );

							if ( index < listView.Items.Count )
							{
								listView.Items[index].Checked = true;
							}
						}
					}
				}
			}
			else if ( c is TextBox )
			{
				TextBox t = c as TextBox;

				o = RestoreValue( storage, prefix + @".Text" );
				if ( o != null )
				{
					t.Text = o as string;
				}
			}
			else if ( c is CheckBox )
			{
				CheckBox cb = c as CheckBox;

				o = RestoreValue( storage, prefix + @".CheckState" );
				if ( o != null )
				{
					cb.CheckState = (CheckState)Enum.Parse(
						typeof( CheckState ),
						o as string,
						true );
				}
			}
			else if ( c is RadioButton )
			{
				RadioButton rb = c as RadioButton;

				o = RestoreValue( storage, prefix + @".Checked" );
				if ( o != null )
				{
					rb.Checked = ConvertHelper.ToBoolean( o );
				}
			}
			else if ( c is DateTimePicker )
			{
				DateTimePicker rb = c as DateTimePicker;

				o = RestoreValue( storage, prefix + @".Value" );
				if ( o != null )
				{
					rb.Value = ConvertHelper.ToDateTime( o );
				}
				o = RestoreValue( storage, prefix + @".Checked" );
				if ( o != null )
				{
					rb.Checked = ConvertHelper.ToBoolean( o );
				}
			}
			else if ( c is CheckedListBox )
			{
				CheckedListBox clb = c as CheckedListBox;

				o = RestoreValue( storage, prefix + @".CheckedIndices" );
				if ( o is string )
				{
					o = StringHelper.DeserializeFromString( o as string );

					if ( o is int[] )
					{
						List<int> selectedIndices =
							new List<int>( o as int[] );

						for ( int i = 0; i < clb.Items.Count; i++ )
						{
							if ( selectedIndices.Contains( i ) )
							{
								clb.SetItemChecked( i, true );
							}
							else
							{
								clb.SetItemChecked( i, false );
							}
						}
					}
				}
			}
			else if ( c is ComboBox )
			{
				ComboBox rb = c as ComboBox;

				o = RestoreValue( storage, prefix + @".SelectedIndex" );
				if ( o != null )
				{
					int index = ConvertHelper.ToInt32( o );

					if ( index <= rb.Items.Count - 1 )
					{
						rb.SelectedIndex = index;
					}
				}

				if ( rb.DropDownStyle == ComboBoxStyle.DropDown )
				{
					rb.Text = RestoreValue( storage, prefix + @".Text" ) as string;
				}
			}
			else
			{
				Debug.Assert(
					false,
					string.Format(
					@"Trying to restore the state of an unknown control type: '{0}'.",
					c.GetType() ) );
			}

			// --

			if ( c is ISaveRestoreState )
			{
				ISaveRestoreState srs = c as ISaveRestoreState;

				if ( !protectRecursion.Contains( srs ) )
				{
					protectRecursion.Add( srs );
					try
					{
						srs.OnSaveState( storage, prefix );
					}
					finally
					{
						protectRecursion.Remove( srs );
					}
				}
			}
		}

		/// <summary>
		/// The opposite to "SaveValue".
		/// </summary>
		/// <param name="name">The name.</param>
		/// <returns>Returns null if not found.</returns>
		public static object RestoreValue(
			string name )
		{
			return RestoreValue( Storage, name );
		}

		/// <summary>
		/// The opposite to "SaveValue".
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <returns>Returns null if not found.</returns>
		public static object RestoreValue(
			IPersistentPairStorage storage,
			string name )
		{
			return RestoreValue( storage, name, null );
		}

		/// <summary>
		/// The opposite to "SaveValue".
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="fallBackValue">The fall back value.</param>
		/// <returns>Returns null if not found.</returns>
		public static object RestoreValue(
			string name,
			object fallBackValue )
		{
			return RestoreValue( Storage, name, fallBackValue );
		}

		/// <summary>
		/// The opposite to "SaveValue".
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <param name="fallBackValue">The fall back value.</param>
		/// <returns>Returns null if not found.</returns>
		public static object RestoreValue(
			IPersistentPairStorage storage,
			string name,
			object fallBackValue )
		{
			return storage.RetrieveValue( name, fallBackValue );
		}

		/// <summary>
		/// The opposite to "SerializeValue".
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="fallBackValue">The fall back value.</param>
		/// <returns>Returns NULL if not found.</returns>
		public static object DeserializeValue(
			string name,
			object fallBackValue )
		{
			return DeserializeValue( Storage, name, fallBackValue );
		}

		/// <summary>
		/// The opposite to "SerializeValue".
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <param name="fallBackValue">The fall back value.</param>
		/// <returns>Returns NULL if not found.</returns>
		public static object DeserializeValue(
			IPersistentPairStorage storage,
			string name,
			object fallBackValue )
		{
			try
			{
				object o = RestoreValue( storage, name );

				if ( o == null || !(o is string) )
				{
					return fallBackValue;
				}
				else
				{
					return StringHelper.DeserializeFromString( o.ToString() );
				}
			}
			catch ( SerializationException x )
			{
				LogCentral.Current.LogDebug(
					@"Silently caught SerializationException, returning fallback value.",
					x );
				return fallBackValue;
			}
		}

		/// <summary>
		/// The opposite to "SerializeValue".
		/// </summary>
		/// <param name="name">The name.</param>
		/// <returns>Returns NULL if not found.</returns>
		public static object DeserializeValue(
			string name )
		{
			return DeserializeValue( Storage, name );
		}

		/// <summary>
		/// The opposite to "SerializeValue".
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="name">The name.</param>
		/// <returns>Returns NULL if not found.</returns>
		public static object DeserializeValue(
			IPersistentPairStorage storage,
			string name )
		{
			object o = RestoreValue( storage, name );

			if ( o == null || !(o is string) )
			{
				return null;
			}
			else
			{
				return StringHelper.DeserializeFromString( o.ToString() );
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Resizing the columns of a list view.
		// ------------------------------------------------------------------

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		public static void ResizeListViewColumns(
			ListView listView )
		{
			ResizeListViewColumns( listView, new ListViewSizeOptions() );
		}

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		/// <param name="columnToStretch">The column to stretch.</param>
		public static void ResizeListViewColumns(
			ListView listView,
			int columnToStretch )
		{
			ResizeListViewColumns( listView, columnToStretch, new ListViewSizeOptions() );
		}

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		/// <param name="sizes">The sizes.</param>
		public static void ResizeListViewColumns(
			ListView listView,
			params double[] sizes )
		{
			ResizeListViewColumns( listView, new ListViewSizeOptions(), sizes );
		}

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		/// <param name="options">The options.</param>
		public static void ResizeListViewColumns(
			ListView listView,
			ListViewSizeOptions options )
		{
			ResizeListViewColumns( listView, listView.Columns.Count - 1, options );
		}

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		/// <param name="columnToStretch">The column to stretch.</param>
		/// <param name="options">The options.</param>
		public static void ResizeListViewColumns(
			ListView listView,
			int columnToStretch,
			ListViewSizeOptions options )
		{
			int width = listView.ClientRectangle.Width;

			if ( options.SubtractVerticalScrollBarWidth )
			{
				width -= VerticalScrollBarWidth;
			}

			width -= DefaultSubtractWidth;

			// The widths of all but the column to stretch.
			for ( int i = 0; i < listView.Columns.Count; ++i )
			{
				if ( i != columnToStretch )
				{
					width -= listView.Columns[i].Width;
				}
			}

			listView.Columns[columnToStretch].Width = width;
		}

		/// <summary>
		/// Resizes the columns of a given list view according to the passed
		/// column widths.
		/// </summary>
		/// <param name="listView">The list view.</param>
		/// <param name="options">The options.</param>
		/// <param name="sizes">Pass a value smaller than 1.0 to specify
		/// the value in percent (0.30 e.g. means 30%), pass a value
		/// of 0.0 to not size the column.</param>
		public static void ResizeListViewColumns(
			ListView listView,
			ListViewSizeOptions options,
			params double[] sizes )
		{
			if ( sizes.Length != listView.Columns.Count )
			{
				throw new ArgumentException(
					LocalizationHelper.Format(
					Resources.Str_ZetaLib_Windows_Common_FormHelper_01,
					LocalizationHelper.CreatePair( @"ColumnCount", listView.Columns.Count ),
					LocalizationHelper.CreatePair( @"SizedCount", sizes.Length ) ),
					@"sizes" );
			}
			else
			{
				// Avoid endless calls.
				if ( !insideSizes.Contains( listView ) )
				{
					insideSizes.Add( listView );

					try
					{
						int width = listView.ClientRectangle.Width;
						if ( options.SubtractVerticalScrollBarWidth )
						{
							width -= VerticalScrollBarWidth;
						}

						width -= DefaultSubtractWidth;

						// First pass - subtract all absolute sizes.
						for ( int i = 0; i < listView.Columns.Count; ++i )
						{
							double size = sizes[i];

							if ( size == 0.0 )
							{
								width -= listView.Columns[i].Width;
							}
							else if ( size <= 1.0 )
							{
								// Do nothing.
							}
							else
							{
								width -= Convert.ToInt32( size );
							}
						}

						// Second pass - actually resize.
						for ( int i = 0; i < listView.Columns.Count; ++i )
						{
							double size = sizes[i];

							if ( size <= 0.0001 )
							{
								// Do nothing.
							}
							else if ( size <= 1.0 )
							{
								// Size percentual.
								int theWidth =
									Convert.ToInt32( (((double)width) * size) );
								ColumnHeader col = listView.Columns[i];
								col.Width = theWidth;
							}
							else
							{
								// Size absolute.
								listView.Columns[i].Width =
									Convert.ToInt32( size );
							}
						}
					}
					finally
					{
						insideSizes.Remove( listView );
					}
				}
			}
		}

		/// <summary>
		/// Avoid duplicates.
		/// </summary>
		private static Set<ListView> insideSizes = new Set<ListView>();

		/// <summary>
		/// Gets the width of the vertical scroll bar.
		/// </summary>
		/// <value>The width of the vertical scroll bar.</value>
		private static int VerticalScrollBarWidth
		{
			get
			{
				return 0;
				/*return SystemInformation.VerticalScrollBarWidth;*/
			}
		}

		/// <summary>
		/// Always subtract a little bit to ensure those randomly appearing
		/// artificial scrollbars disappear.
		/// </summary>
		private const int DefaultSubtractWidth = 4;

		// ------------------------------------------------------------------
		#endregion

		#region ComboBox methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// Gets the selected combo box item's value.
		/// </summary>
		/// <param name="cb">The cb.</param>
		/// <returns></returns>
		public static string GetSelectedComboBoxValue(
			ComboBox cb )
		{
			if ( cb.SelectedItem == null )
			{
				return null;
			}
			else
			{
				if ( cb.SelectedItem is StringPair )
				{
					return (cb.SelectedItem as StringPair).Value;
				}
				else
				{
					return cb.SelectedItem.ToString();
				}
			}
		}

		/// <summary>
		/// Select a combobox item by its value.
		/// </summary>
		/// <param name="cb">The cb.</param>
		/// <param name="val">The val.</param>
		public static void SelectComboBoxByValue(
			ComboBox cb,
			string val )
		{
			if ( val != null )
			{
				foreach ( object o in cb.Items )
				{
					if ( o is StringPair )
					{
						StringPair sp = o as StringPair;

						if ( sp.Value.ToString().ToLower() == val.ToLower() )
						{
							cb.SelectedItem = o;
							break;
						}
					}
					else
					{
						if ( o.ToString().ToLower() == val.ToLower() )
						{
							cb.SelectedItem = o;
							break;
						}
					}
				}
			}
		}

		/// <summary>
		/// Select a combobox item by its value.
		/// </summary>
		/// <param name="cb">The cb.</param>
		/// <param name="val">The val.</param>
		public static void SelectComboBoxByValue(
			ComboBox cb,
			object val )
		{
			if ( val != null )
			{
				foreach ( object o in cb.Items )
				{
					if ( o.Equals( val ) )
					{
						cb.SelectedItem = o;
						break;
					}
				}
			}
		}

		/// <summary>
		/// Select a combobox item by its name.
		/// </summary>
		/// <param name="cb">The cb.</param>
		/// <param name="val">The val.</param>
		public static void SelectComboBoxByName(
			ComboBox cb,
			string val )
		{
			foreach ( object o in cb.Items )
			{
				if ( o is StringPair )
				{
					StringPair sp = o as StringPair;

					if ( sp.Name.ToString().ToLower() == val.ToLower() )
					{
						cb.SelectedItem = o;
						break;
					}
				}
				else
				{
					if ( o.ToString().ToLower() == val.ToLower() )
					{
						cb.SelectedItem = o;
						break;
					}
				}
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private saving overloads.
		// ------------------------------------------------------------------

		/// <summary>
		/// Saves the state of a form.
		/// </summary>
		/// <param name="c">The c.</param>
		private static void SaveState(
			Form c )
		{
			SaveState( Storage, c );
		}

		/// <summary>
		/// Saves the state of a form.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		private static void SaveState(
			IPersistentPairStorage storage,
			Form c )
		{
			string prefix = c.Name;

			SaveValue( storage, prefix + @".Left", c.Left );
			SaveValue( storage, prefix + @".Top", c.Top );
			SaveValue( storage, prefix + @".Width", c.Width );
			SaveValue( storage, prefix + @".Height", c.Height );
			SaveValue( storage, prefix + @".WindowState", Convert.ToInt32( c.WindowState ) );
		}

		/// <summary>
		/// Saves the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		private static void SaveState(
			SplitContainer c )
		{
			SaveState( Storage, c );
		}

		/// <summary>
		/// Saves the state of a control.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		private static void SaveState(
			IPersistentPairStorage storage,
			SplitContainer c )
		{
			int realDistance = 0;
			if ( c.Orientation == Orientation.Vertical )
			{
				if ( c.FixedPanel == FixedPanel.Panel1 )
				{
					realDistance = c.SplitterDistance;
				}
				else
				{
					Debug.Assert(
						c.FixedPanel == FixedPanel.Panel2,
						@"FixedPanel must be Panel2." );

					realDistance = c.Width - c.SplitterDistance;
				}
			}
			else
			{
				Debug.Assert(
					c.Orientation == Orientation.Horizontal,
					@"Orientation must be horizontal." );

				if ( c.FixedPanel == FixedPanel.Panel1 ||
					c.FixedPanel == FixedPanel.None )
				{
					realDistance = c.SplitterDistance;
				}
				else
				{
					Debug.Assert(
						c.FixedPanel == FixedPanel.Panel2,
						@"FixedPanel must be Panel2." );

					realDistance = c.Height - c.SplitterDistance;
				}
			}

			// --

			string prefix = c.Name;

			SaveValue( storage, prefix + @"SplitterDistance", c.SplitterDistance );
			SaveValue( storage, prefix + @"RealSplitterDistance", realDistance );
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private restoring overloads.
		// ------------------------------------------------------------------

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		private static void RestoreState(
			Form c )
		{
			RestoreState( Storage, c );
		}

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		/// <param name="info">The info.</param>
		private static void RestoreState(
			IPersistentPairStorage storage,
			Form c,
			RestoreInformation info )
		{
			// If child, center to parent.
			bool centerParent = !c.TopLevel || c.ParentForm != null;

			bool hasAnythingRestored = false;

			string prefix = c.Name;

			object o = null;
			if ( !centerParent )
			{
				o = RestoreValue( storage, prefix + @".Left" );
				if ( o != null )
				{
					hasAnythingRestored = true;
					c.Left = Convert.ToInt32( o );
				}
				o = RestoreValue( storage, prefix + @".Top" );
				if ( o != null )
				{
					hasAnythingRestored = true;
					c.Top = Convert.ToInt32( o );
				}
			}
			o = RestoreValue( storage, prefix + @".Width" );
			if ( o != null )
			{
				hasAnythingRestored = true;
				c.Width = Convert.ToInt32( o );
			}
			o = RestoreValue( storage, prefix + @".Height" );
			if ( o != null )
			{
				hasAnythingRestored = true;
				c.Height = Convert.ToInt32( o );
			}

			o = RestoreValue( storage, prefix + @".WindowState" );
			if ( o != null )
			{
				hasAnythingRestored = true;
				FormWindowState state = (FormWindowState)Convert.ToInt32( o );

				// Don't allow to start minimized.
				if ( state != c.WindowState &&
					state != FormWindowState.Minimized )
				{
					if ( c.StartPosition != FormStartPosition.Manual )
					{
						c.StartPosition = FormStartPosition.Manual;
					}
					c.WindowState = state;
				}

				if ( state == FormWindowState.Minimized )
				{
					c.WindowState = FormWindowState.Maximized;
				}
			}

			// --

			// 2007-01-28: Zoom if desired.
			if ( !hasAnythingRestored &&
				info != null &&
				info.SuggestZoomPercent > 0 )
			{
				double zoom = (double)info.SuggestZoomPercent / 100.0;

				Size screenSize = SystemInformation.WorkingArea.Size;
				Size windowSize = c.Size;

				int width;
				int height;

				if ( (double)screenSize.Width / (double)windowSize.Width <
					(double)screenSize.Height / (double)windowSize.Height )
				{
					// Scale in X.
					width = (int)((double)screenSize.Width * zoom);
					double fac = (double)width / (double)c.Width;
					height = (int)(fac * (double)c.Height);
				}
				else
				{
					// Scale in Y.
					height = (int)((double)screenSize.Height * zoom);
					double fac = (double)height / (double)c.Height;
					width = (int)(fac * (double)c.Width);
				}

				// Only apply if getting larger.
				if ( width > c.Width && height > c.Height )
				{
					c.Width = width;
					c.Height = height;
				}
			}

			// --

			// If child, center to parent.
			if ( centerParent )
			{
				c.StartPosition = FormStartPosition.CenterParent;
			}
		}

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="c">The c.</param>
		private static void RestoreState(
			SplitContainer c )
		{
			RestoreState( Storage, c );
		}

		/// <summary>
		/// Restores the state of a control.
		/// </summary>
		/// <param name="storage">The storage.</param>
		/// <param name="c">The c.</param>
		private static void RestoreState(
			IPersistentPairStorage storage,
			SplitContainer c )
		{
			string prefix = c.Name;

			object o1 = RestoreValue( storage, prefix + @"SplitterDistance" );
			object o2 = RestoreValue( storage, prefix + @"RealSplitterDistance" );

			if ( o1 != null && o2 != null )
			{
				int distance = Convert.ToInt32( o1 );
				int realDistance = Convert.ToInt32( o2 );

				if ( c.Orientation == Orientation.Vertical )
				{
					if ( c.FixedPanel == FixedPanel.Panel1 ||
						c.FixedPanel == FixedPanel.None )
					{
						c.SplitterDistance = realDistance;
					}
					else
					{
						Debug.Assert(
							c.FixedPanel == FixedPanel.Panel2,
							@"FixedPanel must be Panel2." );

						if ( (c.Width - realDistance) > 0 )
						{
							c.SplitterDistance = c.Width - realDistance;
						}
					}
				}
				else
				{
					Debug.Assert(
						c.Orientation == Orientation.Horizontal,
						string.Format( @"Unknown orientation '{0}'.", c.Orientation ) );

					if ( c.FixedPanel == FixedPanel.Panel1 )
					{
						c.SplitterDistance = realDistance;
					}
					else
					{
						Debug.Assert(
							c.FixedPanel == FixedPanel.Panel2,
							@"You must set one panel inside a splitter to be fixed." );

						if ( (c.Height - realDistance) > 0 )
						{
							c.SplitterDistance = c.Height - realDistance;
						}
					}
				}
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Persistance configuration.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		private static object typeLock = new object();

		/// <summary>
		/// The storage is responsible for actual storing the values.
		/// </summary>
		/// <value>The storage.</value>
		public static IPersistentPairStorage Storage
		{
			get
			{
				lock ( typeLock )
				{
					return storage;
				}
			}
			set
			{
				lock ( typeLock )
				{
					storage = value;
				}
			}
		}

		/// <summary>
		/// The default is to the registry.
		/// </summary>
		private static IPersistentPairStorage storage =
			new PersistentRegistryPairStorage();

		/// <summary>
		/// Protect from being endless recursed.
		/// </summary>
		private static Set<ISaveRestoreState> protectRecursion =
			new Set<ISaveRestoreState>();

		// ------------------------------------------------------------------
		#endregion

		#region Miscellaneous helpers.
		// ------------------------------------------------------------------

		/// <summary>
		/// See http://www.codeproject.com/csharp/begininvoke.asp?msg=1613610#xx1613610xx
		/// Usage:
		/// private void SetLabelText( int number )
		/// {
		/// FormHelper.SyncInvoke( this, delegate()
		/// {
		/// label.Text = number.ToString();
		/// } );
		/// }
		/// </summary>
		/// <param name="control">The control.</param>
		/// <param name="del">The del.</param>
		public static void SyncInvoke(
			 Control control,
			 MethodInvoker del )
		{
			if ( (control != null) && control.InvokeRequired )
			{
				control.Invoke( del, null );
			}
			else
			{
				del();
			}
		}

		/// <summary>
		/// See http://www.codeproject.com/csharp/begininvoke.asp?msg=1613610#xx1613610xx
		/// Usage:
		/// private void SetLabelText( int number )
		/// {
		/// FormHelper.SyncBeginInvoke( this, delegate()
		/// {
		/// label.Text = number.ToString();
		/// } );
		/// }
		/// </summary>
		/// <param name="control">The control.</param>
		/// <param name="del">The del.</param>
		public static void SyncBeginInvoke(
			Control control,
			MethodInvoker del )
		{
			if ( (control != null) && control.InvokeRequired )
			{
				control.BeginInvoke( del, null );
			}
			else
			{
				del();
			}
		}

		/// <summary>
		/// Recursively traverses each control.
		/// </summary>
		/// <param name="parentControl">The parent control.</param>
		/// <param name="action">The action.</param>
		public static void IterateControls(
			Control parentControl,
			Action<Control> action )
		{
			if ( parentControl != null )
			{
				action( parentControl );

				IterateControls( parentControl.Controls, action );
			}
		}

		/// <summary>
		/// Recursively traverses each control.
		/// </summary>
		/// <param name="parentControls">The parent controls.</param>
		/// <param name="action">The action.</param>
		public static void IterateControls(
			Control.ControlCollection parentControls,
			Action<Control> action )
		{
			if ( parentControls != null )
			{
				foreach ( Control c in parentControls )
				{
					IterateControls( c, action );
				}
			}
		}

		// ------------------------------------------------------------------
		#endregion
	}

	/////////////////////////////////////////////////////////////////////////
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Chief Technology Officer Zeta Software GmbH
Germany Germany
Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.

➡️ Give me a tip 🙂

In his free time, he does climbing, running and mountain biking. In 2012 he became a father of a cute boy and in 2014 of an awesome girl.

Some cool, free software from us:

Windows 10 Ereignisanzeige  
German Developer Community  
Free Test Management Software - Intuitive, competitive, Test Plans.  
Homepage erstellen - Intuitive, very easy to use.  
Offline-Homepage-Baukasten

Comments and Discussions