プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

C++/CLIでフォームが表示された時/非表示になった時に処理する。

f:id:paveway:20190914064630j:plain

はじめに

C++/CLIでWindowsアプリを作成した際に、フォームが表示された時とフォームが非表示になった時に処理したい状況がありました。iOSアプリやAndroidアプリでは、そのようなタイミングで呼び出されるライフサイクルメソッドが用意されているのを知っていましたので、Windowsアプリでも同様のライフサイクルメソッドがないか調べてみました。

iOSアプリのライフサイクルメソッド

参考ですがiOSアプリやAndroidアプリでは、フォームに該当するビュークラスの状態に応じて呼び出されるライフサイクルメソッドが、それぞれのタイミングで用意されています。以下はiOSアプリに用意されているライフサイクルメソッドで、それぞれのタイミングで呼び出されます。
(Androidアプリのライフサイクルメソッドは省略します)

メソッド名 説明
loadView カスタムビューの初期化を行うタイミング
viewDidLoad ビューがロードされた後のタイミング
viewWillApper ビューが表示される直前のタイミング
viewWillLayoutSubviews ビューがレイアウトされる直前のタイミング
viewDidLayoutSubviews ビューのレイアウトが完了したタイミング
viewDidApear ビューが表示された後のタイミング
viewWillDisapper ビューが表示されなくなる直前のタイミング
viewDidDisapear ビューが表示されなくなった後のタイミング

Windowsアプリのイベント

同じようにWindowsアプリのフォームクラスにもライフサイクルメソッドがないか調べてみました。 次のサイトにライフサイクルメソッドではありませんが、フォームのそれぞれのタイミングではイベントが発生することがわかりました。

Windows フォームのイベントの順序

フォームが開始されるタイミングで発生するイベント

イベント名 説明
Control.HandleCreated コントロール(おそらくフォームのこと)が生成されたタイミング
Control.BindingContextChanged BindingContextプロパティが変更されたタイミング
Form.Load フォームが最初にロードされたタイミング
Control.VisibleChanged Visibleプロパティが変更されたタイミング
Form.Activated ユーザによってフォームがアクティブ化されたタイミング
Form.Shown フォームが最初に表示されたタイミング

フォームが終了されるタイミングで発生するイベント

イベント名 説明
Form.Closing フォームがクローズされ始めたタイミング
Form.FormClosing フォームがクローズされる前のタイミング
Form.Closed フォームがクローズされた後のタイミング
Form.Deactivate フォームが破棄されるタイミング

イベントの絞り込み

各イベントの発生するタイミングを調べてみて、今回の要求を満たしそうなControl.VisibleChanged/Form.Activated/Form.Shownイベントに着目しました。
まずForm.Shownイベントですが、説明にもあるようにフォームが最初に表示されたタイミングで発生します。そのため"表示されるタイミング"という要求に合致するように思いましたが、フォームが一旦非表示になって再表示された時にForm.Shownイベントは発生しないため使えないことがわかりました。
次にForm.Activatedイベントですが同じくフォームが表示されるタイミングで発生します。そのため通常であれば"表示されるタイミング"という要求を満たします。
しかし今回のアプリの作りが特殊で、複数のフォームを表示しておきボタン押下により表示するフォームを切り替えるといった仕組みにしたため予期せぬタイミングでForm.Activatedイベントが発生してしまい使えませんでした。

Control.VisibleChangedイベント

最後に残ったControl.VisibleChantedイベントですが、説明をみると発するタイミングは"Visibleプロパティが変更されたタイミング"とあります。
次にVisibleプロパティを調べてみると、コントロール(フォーム)が表示されたかどうかの値(Bool値)が設定されるとあります。そのためこのControl.VisibleChangedイベントのイベントハンドラで、Visibleプロパティの状態を判定して、フォームが表示されたタイミング/非表示になったタイミングを判断することにしました。

サンプル

以下のようにフォームのVisibleChangedイベントハンドラを追加して処理を記述しました。

private: System::Void SampleForm_VisibleChanged(System::Object^ sender, System::EventArgs^ e) {
    if (this->Visible)
    {
        // フォームが表示された時の処理
    }
    else
    {
        // フォームが非表示になった時の処理
    }
}

おわりに

今回iOSアプリのライフサイクルメソッドのタイミングとWindowsアプリのイベントのタイミングを整理してみると、似ているようで違うと感じました。感覚的な問題かもしれませんが、Windowsアプリのイベントのタイミングは自分にとっていまいち使いづらいと感じました。 今回調べきれなかったイベントについても機会があれば調べてみたいと思います。