ちょっと面倒だってのでメモ程度に…
WPF/Prism で開発時、スプラッシュウィンドウを表示するのはとても簡単です。
画像ファイルの「ビルドアクション」に対して「SplashScreen」を指定するだけです。
これだけで、「起動直後~メインウィンドウが開くまで」の間指定の画像が表示されます。
この辺参照:
https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/834wpfsplashscreen/wpfsplashscreen.html
って、それだけ?じゃありません。
問題!何のためにスプラッシュウィンドウを表示するか?
答え:ソフトウェア起動前の初期化処理が長い時に間を持たせるため!
って事で、今回は起動前に「シリアル通信」を行っています。
そのため、シリアルケーブル(USBケーブル)が繋がっていれば良いのですが、繋がっていない場合は「再確認」が必要です。
問題点:
1.上記設定の場合、メイン画面が表示されてしまうとスプラッシュウィンドウが消えてしまう。
2.メイン画面が表示されていなくても、エラーメッセージを出しただけでスプラッシュウィンドウが消えてしまう(ケーブル未接続なのに…)
3.全て?を投げうって、メイン画面表示後にダイアログ表示で画像を表示する!(後ろにメイン画面が有ってかっこ悪い!)
+ コーディングがメンドクサイ! + 処理の流れが分かりにくい!
等々、いろいろ問題が出てきます。
2024年4月8日:カスタムスプラッシュウィンドウを出す場合はこっち(画像にバージョン出したりプログレスバー出したり…)
https://blog.goo.ne.jp/pianyi/e/3482b1d1d8be7a55f448b03533d7a194
画像だけのスプラッシュウィンドウを出す場合:
そこで対処方法:
答えはこれ!
簡単な解説:(Prism でやってるけど、Prism使わなくてもほぼ一緒だと思う)
・SplashScreen クラスはフィールドで持たせてしまう。
・コンストラクタの一番最初でスプラッシュウィンドウを表示させてしまう。(後ろにしても良いけど、理由が無いので最初で良いのでは)
・SplashScreen.Show(false); の引数は false で固定。 true にすると、メッセージウィンドウ等を出すと消えます。(逆に言えば「MainWindow.show()」で勝手に消えます)
・OnInitialized を override して、メイン画面を表示する前の動作を行う。
なお、「OnInitialized」の 元処理は「MainWindow.show();」のみが記載されていました。(Githubでソース見てね)
詳細:
「MainWindow.Initialize()」メソッドは、コードビハインド(MainWindow.xaml.cs)内に書いてます。
コードビハインドからViewModelの呼び出しはイベントにしてますが、良いんだよね…?画面のボタンもイベントだし…ね...
流れ「App.xaml → MainWindow.xaml.cs → MainWindowViewModel.cs → Service系」です。
1.「App.xaml → MainWindow.xaml.cs」は直接呼出し「MainWindow.Initialize()」
2.「MainWindow.xaml.cs → MainWindowViewModel.cs」はイベント呼び出し「EventAggregator.GetEvent<DoStartup>().Publish();」
3.「MainWindowViewModel.cs → Service系」は直接呼出し「TestService.Initialize()」
・OnInitialized 処理内で、正常の場合はメインウィドウを表示、異常の場合はメインウィンドウをクローズ(クローズすればそのまま終了します)
・finally でスプラッシュウィンドウを非表示にする。
・OnInitializedメソッドは名前を見る限り「Prism 等の初期化が終わったよ」ってタイミングなので、業務ロジックはこのタイミングで呼び出すのが良いと判断しました
(ちなみにOnStartup は base.OnStartup() を呼び出すと、Prism用の初期化+メイン画面表示まで行われてしまうのでタイミングとして良くないと判断しました)
この流れにすれば、MainWindowViewModel.cs 内でメッセージボックス、その他ダイアログ表示を行ってもスプラッシュウィンドウが閉じる事はありません。
スプラッシュウィンドウが表示中、ずっとエラーメッセージ、再試行等々をユーザの指示を求める。処理する。が出来ます。
(しかしググったページの(1つを除き)ほとんど?がOnStartup内で「表示・初期化・閉じる」の全てを行おうとしてました。表示タイミングは遅いしなぜでしょうか…不思議です…)
これで、シリアルケーブル(USBケーブル)が刺さってない!相手が起動してない!とかのパターンに自然の流れ?で対応出来ますね。(そうなのか?)
良かった良かった!
なお、下記メソッドに色々入れてます。
Appコンストラクタに「多重起動、ログ設定、多言語設定」を入れてます。
OnStartupに「EXEバージョンのチェック」を入れてます。
OnInitializedに「初期化」「設定ファイルの読み込み」を入れてます。
ApplicationExitに「多重起動解除」を入れてます。
ApplicationDispatcherUnhandledExceptionに「ログ出力」「エラーメッセージ表示」を入れてます。
後はPrism 用の設定系のメソッドを入れてます。
時間があれば公開したいが、プロジェクト独自を抜くのがめんどくさ…
なお、下記情報をお待ちしてます!
1.もっと良い方法(や理想の方法やこんなのどう?等)があれば教えてねっ!
2.「new SplashScreen」の第1引数にassemblyを設定する方法をだれか教えて欲しいです!別DLLにある画像を参照できずに断念しました!
WPF/Prism で開発時、スプラッシュウィンドウを表示するのはとても簡単です。
画像ファイルの「ビルドアクション」に対して「SplashScreen」を指定するだけです。
これだけで、「起動直後~メインウィンドウが開くまで」の間指定の画像が表示されます。
この辺参照:
https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/834wpfsplashscreen/wpfsplashscreen.html
って、それだけ?じゃありません。
問題!何のためにスプラッシュウィンドウを表示するか?
答え:ソフトウェア起動前の初期化処理が長い時に間を持たせるため!
って事で、今回は起動前に「シリアル通信」を行っています。
そのため、シリアルケーブル(USBケーブル)が繋がっていれば良いのですが、繋がっていない場合は「再確認」が必要です。
問題点:
1.上記設定の場合、メイン画面が表示されてしまうとスプラッシュウィンドウが消えてしまう。
2.メイン画面が表示されていなくても、エラーメッセージを出しただけでスプラッシュウィンドウが消えてしまう(ケーブル未接続なのに…)
3.全て?を投げうって、メイン画面表示後にダイアログ表示で画像を表示する!(後ろにメイン画面が有ってかっこ悪い!)
+ コーディングがメンドクサイ! + 処理の流れが分かりにくい!
等々、いろいろ問題が出てきます。
2024年4月8日:カスタムスプラッシュウィンドウを出す場合はこっち(画像にバージョン出したりプログレスバー出したり…)
https://blog.goo.ne.jp/pianyi/e/3482b1d1d8be7a55f448b03533d7a194
画像だけのスプラッシュウィンドウを出す場合:
そこで対処方法:
答えはこれ!
public partial class App : PrismApplication { /// <summary> /// 起動時のスプラッシュウィンドウ制御 /// </summary> private SplashScreen SplashScreen; /// <summary> /// コンストラクタ /// </summary> public App() { // スプラッシュウィンドウを表示する SplashScreen = new SplashScreen("Resources/images/Splash.png"); SplashScreen.Show(false); InitializeComponent(); // その他処理があれば行う } /// <summary> /// メイン画面の起動処理 /// </summary> protected override void OnInitialized() { try { if (MainWindow != null) { if (((Test.MainWindow.Views.MainWindow)MainWindow).Initialize()) { // 初期化出来たので画面を表示する MainWindow.Show(); } else { // 初期化出来なかったので終了する MainWindow.Close(); } } } finally { // 画面表示/閉じるにかかわらず、スプラッシュウィンドウを閉じる SplashScreen.Close(TimeSpan.Zero); } } } }
簡単な解説:(Prism でやってるけど、Prism使わなくてもほぼ一緒だと思う)
・SplashScreen クラスはフィールドで持たせてしまう。
・コンストラクタの一番最初でスプラッシュウィンドウを表示させてしまう。(後ろにしても良いけど、理由が無いので最初で良いのでは)
・SplashScreen.Show(false); の引数は false で固定。 true にすると、メッセージウィンドウ等を出すと消えます。(逆に言えば「MainWindow.show()」で勝手に消えます)
・OnInitialized を override して、メイン画面を表示する前の動作を行う。
なお、「OnInitialized」の 元処理は「MainWindow.show();」のみが記載されていました。(Githubでソース見てね)
詳細:
「MainWindow.Initialize()」メソッドは、コードビハインド(MainWindow.xaml.cs)内に書いてます。
コードビハインドからViewModelの呼び出しはイベントにしてますが、良いんだよね…?画面のボタンもイベントだし…ね...
流れ「App.xaml → MainWindow.xaml.cs → MainWindowViewModel.cs → Service系」です。
1.「App.xaml → MainWindow.xaml.cs」は直接呼出し「MainWindow.Initialize()」
2.「MainWindow.xaml.cs → MainWindowViewModel.cs」はイベント呼び出し「EventAggregator.GetEvent<DoStartup>().Publish();」
3.「MainWindowViewModel.cs → Service系」は直接呼出し「TestService.Initialize()」
・OnInitialized 処理内で、正常の場合はメインウィドウを表示、異常の場合はメインウィンドウをクローズ(クローズすればそのまま終了します)
・finally でスプラッシュウィンドウを非表示にする。
・OnInitializedメソッドは名前を見る限り「Prism 等の初期化が終わったよ」ってタイミングなので、業務ロジックはこのタイミングで呼び出すのが良いと判断しました
(ちなみにOnStartup は base.OnStartup() を呼び出すと、Prism用の初期化+メイン画面表示まで行われてしまうのでタイミングとして良くないと判断しました)
この流れにすれば、MainWindowViewModel.cs 内でメッセージボックス、その他ダイアログ表示を行ってもスプラッシュウィンドウが閉じる事はありません。
スプラッシュウィンドウが表示中、ずっとエラーメッセージ、再試行等々をユーザの指示を求める。処理する。が出来ます。
(しかしググったページの(1つを除き)ほとんど?がOnStartup内で「表示・初期化・閉じる」の全てを行おうとしてました。表示タイミングは遅いしなぜでしょうか…不思議です…)
これで、シリアルケーブル(USBケーブル)が刺さってない!相手が起動してない!とかのパターンに自然の流れ?で対応出来ますね。(そうなのか?)
良かった良かった!
なお、下記メソッドに色々入れてます。
Appコンストラクタに「多重起動、ログ設定、多言語設定」を入れてます。
OnStartupに「EXEバージョンのチェック」を入れてます。
OnInitializedに「初期化」「設定ファイルの読み込み」を入れてます。
ApplicationExitに「多重起動解除」を入れてます。
ApplicationDispatcherUnhandledExceptionに「ログ出力」「エラーメッセージ表示」を入れてます。
後はPrism 用の設定系のメソッドを入れてます。
時間があれば公開したいが、プロジェクト独自を抜くのがめんどくさ…
なお、下記情報をお待ちしてます!
1.もっと良い方法(や理想の方法やこんなのどう?等)があれば教えてねっ!
2.「new SplashScreen」の第1引数にassemblyを設定する方法をだれか教えて欲しいです!別DLLにある画像を参照できずに断念しました!