C# 汎用スプラッシュスクリーン (WinForms)

WinForms用の汎用スプラッシュスクリーンサポートクラスを作ってみた

動作としては、
Application.Run()でスプラッシュスクリーンを起動、
スプラッシュスクリーンは初期化済みオブジェクトを返す初期化関数(Func<T>)を
コンストラクタの引数に取り、スレッドプール(Task)上で初期化処理を実行、
初期化処理が終了したらメインウィンドウを作成、と同時に
初期化済みオブジェクトをメインウィンドウに渡す。
メインウィンドウのCloseイベントにスプラッシュスクリーンを閉じる関数を追加
メインウィンドウを開いて、スプラッシュスクリーンを隠すという手順になります。

//---------------------
/// <summary>
/// ジェネリックでは引数付きのコンストラクタを利用できないので
///                   Factoryを使用して対処する
/// 引数付きのコンストラクタ世を呼び出して新しいオブジェクトを作成する。
/// </summary>
/// <typeparam name="argT1">コンストラクタに渡す引数</typeparam>
/// <typeparam name="TNewObject">引数付きコンストラクタを持つクラス</typeparam>
public interface IFactory<argT1,TNewObject>
{
    TNewObject Create(argT1 t1);
}

//-----------------------

/// <summary>
///   スプラッシュスクリーンサポートクラス
///   適当なForm内でこのオブジェクトを作成すると
///   そのFormがスプラッシュスクリーンとして動作するようになる
/// </summary>
/// <typeparam name="InitObject">
///   スプラッシュスクリーンの表示中に初期化したいオブジェクトの型
/// </typeparam>
/// <typeparam name="MainForm">
///  初期化終了時に開くForm
/// </typeparam>
/// <typeparam name="FactoryType">
///   初期化済みInitObjectを引数に取りMainFormのコンストラクタを呼び出す
///               Factoryクラス
/// </typeparam>
public class SplashScreenSupporter<InitObject,MainForm, FactoryType>
    where MainForm:Form
    where FactoryType : IFactory<InitObject,MainForm>, new()
        
{
    Func<InitObject> action_;
    Form screen_;
    
    /// <summary>
    ///  引数に受け取ったFormをスプラッシュスクリーンになるように設定する。
    ///  初期化処理はaction内で行う
    /// </summary>
    /// <param name="f">スプラッシュスクリーンとして動作させたいForm</param>
    /// <param name="action">
    ///   初期化を行い、初期化済みオブジェクトを返す関数
    //// </param>
    public  SplashScreenSupporter(Form f,Func<InitObject> action)
    {
        action_ = action;
        screen_ = f;

        // タイトルバーなどを非表示にする
        screen_.FormBorderStyle = FormBorderStyle.None;

        // 初期位置をスクリーン中央にする
        screen_.StartPosition = FormStartPosition.CenterScreen;

        //タスクバーに表示しないようにする。
        screen_.ShowInTaskbar = false;

        //スプラッシュスクリーンの表示時に行う処理を登録
        screen_.Shown += Splash;
        
    }
    
    /// <summary>
    ///  スプラッシュスクリーンが表示された時の動作。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Splash(object sender, EventArgs e)
    {
        // コンストラクタで引数として受け取った初期化関数を非同期実行
        Task<InitObject>.Factory.StartNew(action_)
        .ContinueWith
        (
            (Tr) =>
            {
                //初期化終了後UIスレッドに処理を戻す。
                screen_.BeginInvoke(
                    new Action<InitObject>((v) =>
                    {
                        // vは初期化関数が返す初期化済みオブジェクト
                        if (v == null)
                        {
                            // nullなら初期化失敗でアプリ終了
                            screen_.Close();
                        }
                        else //初期化出来ていた場合。
                        {
                            // メインウィンドウを作成、
                            // ジェネリックで引数付きコンストラクタは使えないので
                            // Factory経由で初期化済みオブジェクトを渡す。
                            var factory = new FactoryType();
                            var newform = factory.Create(v);

                            // メインウィンドウが閉じた場合
                            // スプラッシュスクリーンも閉じてアプリ終了
                            newform.FormClosed +=(s,arg) =>{ screen_.Close(); };
                                
                            // メインウィンドウを開いて、
                            // スプラッシュスクリーンは隠す。
                            newform.Show();
                            screen_.Hide();
                        }
                    }), Tr.Result
                );
            }
        );
    }
}
//---------------------------

使い方

//---------------------------
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(
            new SplashScreen<InitObject ,MainForm,MainFormFactory>(Initialize)
        );
    }

    InitObject Initialize()
    {
        // スプラッシュスクリーン表示中に行いたい初期化処理をココで行う
        return 初期化済みオブジェクト;
    }

    /// <summary>
    ///  初期化済みInitObjectを受け取ってMainFormに渡す
    /// </summary>
    public class MainFormFactory
      : IFactory<InitObject,MainForm>
    {
        public MainForm Create(InitObject k)
        {
            return new MainForm(k);
        }
    }
}
//-----------------
// スプラッシュスクリーン
public partial class SplashScreen<InitObject,MainWindow,MainWindowFactory>
    :Form
    where MainWindow : Form
    where MainWindowFactory:IFactory<InitObject,MainWindow >,new()
{
    SplashScreenSupporter<InitObject, MainWindow, MainWindowFactory > ss_;

    public SplashScreen(Func<InitObject> InitFunc)
    {
        InitializeComponent();
        ss_ = new SplashScreenSupporter
            <InitObject, MainWindow, MainWindowFactory>(this, InitFunc);
    }
}

//------------------
// メインウィンドウ
public partial class MainForm : Form
{
    // 初期化済みオブジェクトをコンストラクタで受け取る
    public MainForm(InitObject o)
    {

    }
}
//------------------
広告

akatukisiden について

フリーランスプログラマ 使用言語はC++,C#とそのつなぎのC++/CLI 専門はクライアントアプリ開発
カテゴリー: C#, Windows Forms タグ: , , , , パーマリンク

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中