.NET Fx:ShowDialog、Show の実験

定期的に実行されるタイマーイベントハンドラの中で、フォームやメッセージボックスを条件を変えて表示し、その時の挙動を確認した。

実験コードの雛形は以下のようなコード。

public class Form1 : Form
{
    public Form1()
    {
        ...
        this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        // ここに実験コードを書く
    }
}

調査環境

実験1:同一フォームを2回モーダル表示する

form2.ShowDialog(); // オーナーの指定有無による挙動の違いはなかった

一度目の ShowDialog() は問題なくフォームが表示されるが、二度目の ShowDialog() の呼び出しで System.InvalidOperation 例外が発生した。
例外メッセージは「既に表示されているフォームをモーダルダイアログボックスとして表示できません。ShowDialog を呼び出す前に、フォームの Visible プロパティを false にしてください」という内容。

2022-12-07-2250.png

例外はこの場所でスローされている。 2022-12-07-2337.png

参考

Form.ShowDialog() のリファレンス実装

実験2:別フォームを1回ずつモーダル表示する

if (count == 0) {
    count++;
    form2.ShowDialog();
} else if (count == 1) {
    count++;
    form3.ShowDialog();
}

これは問題なく form2 も form3 も表示され、form3 は form2 の上に表示された。
以下のようにオーナーを指定した場合でも挙動に違いはなかった。

if (count == 0) {
    count++;
    form2.ShowDialog(this);
} else if (count == 1) {
    count++;
    form3.ShowDialog(form2);
}

実験3:同一フォームを2回モードレス表示する

form2.Show();

この結果は・・・form2 は 1つしか表示されなかった。
実装は、オーナーを指定しない場合は、Visible = true にしているだけだった。 2022-12-07-2355.png

一方で、オーナーを指定した場合はどうなるか。

form2.Show(this);

この結果は・・・二度目の Show(this) の呼び出しで、実験1(同一フォームを2回モーダル表示する)と同じ例外が発生した。 2022-12-08-0000.png

参考

実験4:別フォームを1回ずつモードレス表示する

まずは、オーナーを指定しないケース。

if (count == 0) {
    count++;
    form2.Show();
} else if (count == 1) {
    count++;
    form3.Show();
}

この結果は・・・問題なく form2、form3 がモードレス表示された。オーナーを指定していないので、Z オーダーの順番は任意に変更できる。

次に、オーナーを指定した場合はどうなるか・・・

if (count == 0) {
    count++;
    form2.Show(this);
} else if (count == 1) {
    count++;
    form3.Show(form2);
}

こちらも問題なく form2, form3 がモードレス表示された。オーナーを指定したことで Z オーダーの順番は form1 < form2 < form3 となった。

実験5:メッセージボックスを複数回表示する

MessageBox.Show("fired"); // オーナーの指定有無による挙動の違いはなかった

メッセージボックスが複数個表示された。 2022-12-09-2041.png

参考

まとめ

実験した範囲内で例外が発生するのは以下のケースだった。

  • すでにモーダル表示されているフォームを、再度モーダル表示しようとした場合
  • オーナーを指定してすでにモードレス表示されているフォームを、再度モードレス表示しようとした場合(※オーナーを指定しない場合は例外は発生しない)