Kwan.Delegates:
Splash.cs:
namespace
Kwan.Delegates
{
/// <summary>
/// Encapsulates a method that has one parameter and doesn't return a value.
/// </summary>
/// <typeparam name="T"> The type of the parameter of the method that this delegate encapsulates. </typeparam>
/// <param name="val"> The parameter of the method that this delegate encapsulates. </param>
public delegate void Action < T > (T val);
/// <summary>
/// Encapsulates a method that has two parameters and doesn't return a value
/// , which is used to find a property on the object by name and set its value
/// </summary>
/// <typeparam name="T"> The type of the parameter of the method that this delegate encapsulates. </typeparam>
/// <param name="propertyName"> The name of the property </param>
/// <param name="val"> The parameter of the method that this delegate encapsulates. </param>
public delegate void Set < T > ( string propertyName, T val);
}
{
/// <summary>
/// Encapsulates a method that has one parameter and doesn't return a value.
/// </summary>
/// <typeparam name="T"> The type of the parameter of the method that this delegate encapsulates. </typeparam>
/// <param name="val"> The parameter of the method that this delegate encapsulates. </param>
public delegate void Action < T > (T val);
/// <summary>
/// Encapsulates a method that has two parameters and doesn't return a value
/// , which is used to find a property on the object by name and set its value
/// </summary>
/// <typeparam name="T"> The type of the parameter of the method that this delegate encapsulates. </typeparam>
/// <param name="propertyName"> The name of the property </param>
/// <param name="val"> The parameter of the method that this delegate encapsulates. </param>
public delegate void Set < T > ( string propertyName, T val);
}
Splash.cs:
namespace
Kwan.Winform
{
using System;
using System.Threading;
using System.Windows.Forms;
using System.Reflection;
using Kwan.Delegates;
/// <summary>
/// A bridge class that connect a main form with a splash form
/// </summary>
/// <typeparam name="TForm"> Type of the splash form </typeparam>
/// <example>
/// In the entry method of the application:
/// <code>
/// [STAThread]
/// static void Main()
/// {
/// Application.EnableVisualStyles();
/// Application.SetCompatibleTextRenderingDefault(false);
///
/// Splash<MySplashForm>.Show();
/// MainForm form = new MainForm();
/// Application.Run(form);
/// }
/// </code>
/// And terminate the splash form in the loading code of the main form:
/// <code>
/// private void MainForm_Load(object sender, EventArgs e)
/// {
/// Splash<MySplashForm>.Close();
/// }
/// </code>
/// </example>
/// <remarks> TO-DO: Ensure thread-safety of cross-thread calls in this class </remarks>
public class Splash < TForm > where TForm : Form, new ()
{
#region Fields
/// <summary>
/// The splash form
/// </summary>
private static TForm _splashForm = null ;
/// <summary>
/// The splash working thread
/// </summary>
private static Thread _splashThread = null ;
#endregion
#region Properties
/// <value>
/// Get the reference of the splash form
/// </value>
/// <remarks> Programmers must warrant the thread-safety of cross-thread calls </remarks>
public static TForm SplashForm
{
get { return _splashForm; }
}
#endregion
#region Public Methods
/// <summary>
/// Show the splash
/// </summary>
public static void Show()
{
if (_splashThread != null )
return ;
_splashThread = new Thread(
() =>
{
_splashForm = new TForm();
Application.Run(_splashForm);
});
_splashThread.IsBackground = true ;
_splashThread.SetApartmentState(ApartmentState.STA);
_splashThread.Start();
}
/// <summary>
/// Close the splash form
/// </summary>
/// <remarks> This method is called from the main form </remarks>
public static void Close()
{
if (_splashThread == null ) return ;
if (_splashForm == null ) return ;
try
{
_splashForm.Invoke( new MethodInvoker(_splashForm.Close));
}
catch (Exception ex) { }
_splashThread = null ;
_splashForm = null ;
}
/// <summary>
/// Set the property of the splash form
/// </summary>
/// <typeparam name="T"> Type of the input value </typeparam>
/// <param name="propertyName"> The name of the property to be set </param>
/// <param name="val"> The value of the input value </param>
/// <example>
/// First expose the value of the progress bar control in the splash form:
/// <code>
/// public int Progress
/// {
/// get { return _progressBar.Value; }
/// set { _progressBar.Value = value; }
/// }
/// </code>
/// Set the properties of the splash form, simulating the loading procedure:
/// <code>
/// private void MainForm_Load(object sender, EventArgs e)
/// {
/// Splash<MySplashForm>.Set<string>("Text", "Loading");
/// int p=1;
/// while (Splash<MySplashForm>.SplashForm.Progress < 100)
/// {
/// System.Threading.Thread.Sleep(20);
/// Splash<MySplashForm>.Set<int>("Progress", p);
/// p++;
/// }
/// }
/// </code>
/// </example>
/// <exception cref="InvalidOperationException"> Property cannot be found </exception>
/// <exception cref="InvalidOperationException"> The type of input value does not match the property type </exception>
public static void Set < T > ( string propertyName, T val)
{
PropertyInfo property = typeof (TForm).GetProperty(propertyName);
if (property == null )
throw new InvalidOperationException( " Property cannot be found " );
if (property.PropertyType != typeof (T))
throw new InvalidOperationException( " The type of input value does not match the property type " );
if (_splashForm.InvokeRequired)
_splashForm.Invoke( new Set < T > (Splash < TForm > .Set < T > ), new object [] { propertyName, val });
else
property.SetValue(_splashForm, val, null );
}
#endregion
}
}
{
using System;
using System.Threading;
using System.Windows.Forms;
using System.Reflection;
using Kwan.Delegates;
/// <summary>
/// A bridge class that connect a main form with a splash form
/// </summary>
/// <typeparam name="TForm"> Type of the splash form </typeparam>
/// <example>
/// In the entry method of the application:
/// <code>
/// [STAThread]
/// static void Main()
/// {
/// Application.EnableVisualStyles();
/// Application.SetCompatibleTextRenderingDefault(false);
///
/// Splash<MySplashForm>.Show();
/// MainForm form = new MainForm();
/// Application.Run(form);
/// }
/// </code>
/// And terminate the splash form in the loading code of the main form:
/// <code>
/// private void MainForm_Load(object sender, EventArgs e)
/// {
/// Splash<MySplashForm>.Close();
/// }
/// </code>
/// </example>
/// <remarks> TO-DO: Ensure thread-safety of cross-thread calls in this class </remarks>
public class Splash < TForm > where TForm : Form, new ()
{
#region Fields
/// <summary>
/// The splash form
/// </summary>
private static TForm _splashForm = null ;
/// <summary>
/// The splash working thread
/// </summary>
private static Thread _splashThread = null ;
#endregion
#region Properties
/// <value>
/// Get the reference of the splash form
/// </value>
/// <remarks> Programmers must warrant the thread-safety of cross-thread calls </remarks>
public static TForm SplashForm
{
get { return _splashForm; }
}
#endregion
#region Public Methods
/// <summary>
/// Show the splash
/// </summary>
public static void Show()
{
if (_splashThread != null )
return ;
_splashThread = new Thread(
() =>
{
_splashForm = new TForm();
Application.Run(_splashForm);
});
_splashThread.IsBackground = true ;
_splashThread.SetApartmentState(ApartmentState.STA);
_splashThread.Start();
}
/// <summary>
/// Close the splash form
/// </summary>
/// <remarks> This method is called from the main form </remarks>
public static void Close()
{
if (_splashThread == null ) return ;
if (_splashForm == null ) return ;
try
{
_splashForm.Invoke( new MethodInvoker(_splashForm.Close));
}
catch (Exception ex) { }
_splashThread = null ;
_splashForm = null ;
}
/// <summary>
/// Set the property of the splash form
/// </summary>
/// <typeparam name="T"> Type of the input value </typeparam>
/// <param name="propertyName"> The name of the property to be set </param>
/// <param name="val"> The value of the input value </param>
/// <example>
/// First expose the value of the progress bar control in the splash form:
/// <code>
/// public int Progress
/// {
/// get { return _progressBar.Value; }
/// set { _progressBar.Value = value; }
/// }
/// </code>
/// Set the properties of the splash form, simulating the loading procedure:
/// <code>
/// private void MainForm_Load(object sender, EventArgs e)
/// {
/// Splash<MySplashForm>.Set<string>("Text", "Loading");
/// int p=1;
/// while (Splash<MySplashForm>.SplashForm.Progress < 100)
/// {
/// System.Threading.Thread.Sleep(20);
/// Splash<MySplashForm>.Set<int>("Progress", p);
/// p++;
/// }
/// }
/// </code>
/// </example>
/// <exception cref="InvalidOperationException"> Property cannot be found </exception>
/// <exception cref="InvalidOperationException"> The type of input value does not match the property type </exception>
public static void Set < T > ( string propertyName, T val)
{
PropertyInfo property = typeof (TForm).GetProperty(propertyName);
if (property == null )
throw new InvalidOperationException( " Property cannot be found " );
if (property.PropertyType != typeof (T))
throw new InvalidOperationException( " The type of input value does not match the property type " );
if (_splashForm.InvokeRequired)
_splashForm.Invoke( new Set < T > (Splash < TForm > .Set < T > ), new object [] { propertyName, val });
else
property.SetValue(_splashForm, val, null );
}
#endregion
}
}