連載
» 2005年05月26日 05時00分 公開

.NET TIPS:モーダル・ダイアログやモードレス・ダイアログを表示するには?

[一色政彦,デジタルアドバンテージ]
.NET TIPS
Insider.NET


「.NET TIPS」のインデックス

連載目次

 Windowsフォームを使ったアプリケーションでは、エラー・メッセージなどの情報をユーザーに表示したり、逆にユーザーが何らかの設定情報を入力したりすることなどに特化したウィンドウを使用する場合がある。例えば、「TIPS:メッセージ・ボックスを表示するには?」で解説した「情報確認」を行うためのメッセージ・ボックスや「TIPS:[フォルダの参照]ダイアログを使用するには?」で解説した「設定入力」を行うための[フォルダの参照]ダイアログ・ボックスなどがそれに該当する。

 これらのダイアログ・ボックスは、情報確認や設定入力などに特化した「ユーザー対話」形式のウィンドウであるという点で、ほかのウィンドウとは区別される。「ユーザー対話」という語句は英語の「dialog(ダイアログ)」に相当する。このような形式のウィンドウが「ダイアログ・ボックス」(以降「ダイアログ」と略す)と呼ばれるのはこのためだ。

 ダイアログはユーザーとの対話を主眼にしているため、多くの場合、アプリケーションの最前面に表示される。これはユーザーが認知しやすいだけでなく、ユーザーに参照や入力を確実に行わせる効果もある。またダイアログは、基本的にメニュー・バーやツール・バーを搭載しておらず、ダイアログ上の[OK]ボタン、[キャンセル]ボタン、[閉じる]ボタンなどをクリックすることにより、そのダイアログが閉じるという特徴がある。以下の画面は、Visual Studio .NETで使用されているダイアログの例だ。

Visual Studio .NETで使用されているダイアログ・ボックスの例 Visual Studio .NETで使用されているダイアログ・ボックスの例
多くの場合、アプリケーションの最前面に表示され、ユーザーが認知しやすいだけでなく、ユーザーに参照や入力を確実に行わせる効果がある。メニュー・バーやツール・バーは基本的に持っていない。[OK]ボタンあるいは[キャンセル]ボタンをクリックするとダイアログは閉じる。

 上記の画面の例では、メイン・ウィンドウがあって、そのサブ・ウィンドウとしてダイアログが表示されている。しかしダイアログは、このようなサブ・ウィンドウとして表示されるだけでなく、ダイアログ単独で表示される場合ある。例えば、Windowsの[スタート]メニューにある[ファイル名を指定して実行]ダイアログは、単体で表示されるダイアログの1つである。

単体で表示されるダイアログの例 単体で表示されるダイアログの例
[スタート]メニューの[ファイル名を指定して実行]で表示される[ファイル名を指定して実行]ダイアログ。

ダイアログ・ボックスを表示する2つの方法

 このようなダイアログを表示するとき、それが画面に現れてから閉じられるまで、ユーザーにそのダイアログ以外の操作を行わせたくない場合がある。例えば、[名前を付けてファイルを保存]ダイアログを表示している最中は、アプリケーション本体での編集操作は禁止したいかもしれない。Windowsのダイアログは、そのような場合に対応した表示も行うことができる。このような表示を行うダイアログは「モーダル・ダイアログ・ボックス(modal dialog box)」と呼ばれる。モーダル・ダイアログを表示している間は、そのダイアログ上での操作しかできない(そのダイアログを閉じなければ、アプリケーションのメイン・ウィンドウはアクティブにならない。ただし別のアプリケーションをアクティブにすることは可能)。いま述べた「ファイルの保存」を始め、オプション設定用のダイアログなど、アプリケーションで利用される多くのダイアログの表示形式はこのタイプだ。

モーダル・ダイアログの例 モーダル・ダイアログの例
モーダル・ダイアログを表示している間は、そのダイアログ上での操作しかできない。この例では、[名前を付けてファイルを保存]ダイアログ上の操作のみが可能で、アプリケーションのメイン画面上での操作はできない。

 逆に、ダイアログを表示している間にも、そのダイアログ以外の操作を許可したい場合がある。例えば、Visual Studio .NETの[検索]ダイアログを表示している最中は、検索(ダイアログの操作)を続けながら、それと同時に検索中のファイルの編集(そのダイアログ以外の操作)も行いたいだろう。Windowsのダイアログは、そのような場合に対応した表示も可能である。このような表示を行うダイアログは「モードレス・ダイアログ・ボックス(modeless dialog box)」と呼ばれる。

モードレス・ダイアログの例 モードレス・ダイアログの例
ダイアログを表示している最中も、そのダイアログ以外の処理が実行できる。この例では、[検索]ダイアログ上の操作だけでなく、ファイルの編集も行うことができる。
  (1)モードレスの[検索]ダイアログが表示されている。
  (2)[検索]ダイアログが表示されていても、ファイルの編集を行うことができる。

 本稿では、モーダル・ダイアログとモードレス・ダイアログの作成方法について解説する。

ダイアログ・ボックスを作成する

 まずはダイアログを作成する必要がある。実は、モーダル・ダイアログやモードレス・ダイアログは単に表示方法が違うだけで、ダイアログ自体に大きな違いはない。つまり、モーダル・ダイアログを作成する場合も、モードレス・ダイアログを作成する場合も、ほとんど同じダイアログでよい。

(1).NET Frameworkにおけるダイアログは、Formクラス(System.Windows.Forms名前空間)を継承したクラスのインスタンスである(以降、これをDialogオブジェクトと記述する)。ただし、そのフォームを通常のウィンドウではなく、ダイアログとして見せるために、FormBorderStyleプロパティをFixedDialog(FormBorderStyle列挙体)に設定する。

(2)一般的なダイアログでは、ダイアログ画面最上部のタイトル・バー(もしくはキャプション・バー)に表示される[最小化]ボタンや[最大化/元に戻す]ボタンがない場合も多い。そのようにダイアログを構成するには、DialogオブジェクトのMinimizeBoxプロパティ(最小化ボタン)、MaximizeBoxプロパティ(最大化ボタン)をそれぞれfalseに設定すればよい。さらにDialogオブジェクトのControlBoxプロパティもfalseにすれば、[閉じる]ボタンも含めてすべてのボタンがなくなる。ちなみにControlBoxとは、タイトル・バーに表示される小さなアイコン(DialogオブジェクトのIconプロパティで設定できる)とそこから表示されるシステム・メニュー(システム・メニューを表示するには、アイコンを左クリックするか、タイトル・バーを右クリックする)のことだ。

ダイアログに使われるボタンの例 ダイアログに使われるボタンの例

(3)最後に、ダイアログを閉じるための[閉じる]ボタンをダイアログ上に追加する。

 以上の3つの手順を記述したサンプル・コードを次に示す。

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsApplication1
{
  // (1) Formクラスから継承したダイアログのクラス
  public class TestDlg : System.Windows.Forms.Form
  {
    private System.Windows.Forms.Button button1;
    private System.ComponentModel.Container components = null;

    // コンストラクタ(初期化処理などを呼び出す)
    public TestDlg()
    {
      InitializeComponent();
    }

    // 後処理(使用されているリソースの解放など)
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if(components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

    // 初期化処理(コントロール属性の設定など)
    private void InitializeComponent()
    {
      // (3) [閉じる]ボタンの追加
      this.button1 = new System.Windows.Forms.Button();

      // ダイアログとコントロールの属性を調整するため、
      // ダイアログのレイアウト処理を一時停止する
      this.SuspendLayout();

      //
      // [閉じる]ボタンの初期化
      //
      this.button1.DialogResult = 
        System.Windows.Forms.DialogResult.Cancel;
      this.button1.Location = new System.Drawing.Point(48, 32);
      this.button1.Name = "button1";
      this.button1.TabIndex = 0;
      this.button1.Text = "閉じる";
      this.button1.Click += 
        new System.EventHandler(this.button1_Click);

      //
      // ダイアログ(TestDlg)の初期化
      //
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
      this. AcceptButton = this.button1;  // モーダル・ダイアログの場合(後述)
      this.ClientSize = new System.Drawing.Size(184, 78);
      this.Controls.Add(this.button1);
      this.FormBorderStyle = 
        System.Windows.Forms.FormBorderStyle.FixedDialog;
      this.MaximizeBox = false;  // (2) [最大化]ボタンの無効化
      this.MinimizeBox = false;  // (2) [最小化]ボタンの無効化
      this.Name = "TestDlg";
      this.Text = "TestDlg";

      // ダイアログとコントロールの初期化が終わったので、
      // レイアウト処理の一時停止を解除する
      this.ResumeLayout(false);
    }

    // モードレス・ダイアログの場合に必要(後述)。
    // モーダル・ダイアログの場合でも上記のAcceptButtonプロパティ
    // またはCancelButtonプロパティを設定していない場合には必要。
    // [閉じる]ボタンを押されたとき、ダイアログを閉じる
    private void button1_Click(object sender, System.EventArgs e)
    {
      this.Close();
    }
  }
}

ダイアログのクラスを記述したサンプル・プログラム
サンプル・プログラム(C#:dialog1.cs、VB.NET:dialog1.vb)のダウンロード

モーダル・ダイアログを表示するには?

 作成したダイアログをモーダル・ダイアログとして起動するには、DialogオブジェクトのShowDialogメソッドを呼び出すだけだ。なおこのShowDialogメソッドは、ダイアログが閉じられるまでメソッドが終了しない(処理が次に進まない)。

 以下にそのコードを示す(先ほどのダイアログ自体のクラスではなく、そのダイアログを呼び出す側のクラスに実装するコード)。

private void button1_Click(object sender, System.EventArgs e)
{
  // モーダル・ダイアログを表示する
  TestDlg dlg = new TestDlg();
  DialogResult dlgRet = dlg.ShowDialog(this);
}

モーダル・ダイアログを表示するサンプル・コード
サンプル・プログラム(C#:dialog2.cs、VB.NET:dialog2.vb)のダウンロード
ダイアログを表示するフォームのオブジェクト(フォームのクラス内では、C#ならthisオブジェクト、VB.NETならMeオブジェクトとして参照できる)をShowDialogメソッドの第1パラメータに引き渡すと、ダイアログのオーナー(所有者)となるトップレベル・ウィンドウとして指定できる。もしこのパラメータを指定しないと、現在アクティブなウィンドウが自動的にダイアログのオーナーになる。

 ShowDialogメソッドの戻り値は、ダイアログの処理結果を示すためのもので、Dialogオブジェクト(=フォーム)のDialogResultプロパティの値である。このDialogResultプロパティの値には、DialogResult列挙体の値が使われる。

 モーダル・ダイアログ上のButtonオブジェクト(本稿の例では、[閉じる]ボタン)を、DialogオブジェクトのAcceptButtonプロパティに設定すれば、ユーザーがフォーム上で[Enter]キーを押したときに、そのボタンのクリック処理が実行されるようになる。また、CancelButtonプロパティを設定しておけば、ユーザーがフォーム上で[Escape]キーを押したときに、そのボタンのクリック処理が実行されるようになる。

 ボタンのDialogResultプロパティに、「DialogResult.Cancel」や「DialogResult.OK」などのDialogResult列挙体の値が設定されている場合、そのボタンがクリックされるとDialogオブジェクトのDialogResultプロパティに対してそのDialogResult列挙体の値が設定される。モーダル・ダイアログでは、DialogオブジェクトのDialogResultプロパティに「DialogResult.None」以外の値が設定されると、自動的にダイアログが終了する仕組みになっている。このため、ボタンのDialogResultプロパティを設定すれば、ボタンのClickイベント・ハンドラでダイアログの終了処理を実装する必要はない(ただし次に紹介するモードレス・ダイアログの場合は、Closeメソッドなどによるダイアログの終了処理が必要となる)。

 なお、DialogオブジェクトのCancelButtonプロパティを設定すると、設定されたボタンのDialogResultプロパティに「DialogResult.Cancel」が自動的に設定される(ただし、この自動設定が行われるのは、ボタンのDialogResultプロパティの値が「DialogResult.None」の場合のときだけだ)。しかし、AcceptButtonプロパティを設定した場合では、設定されたボタンのDialogResultプロパティの値は変更されないので注意してほしい。

 ちなみに、モーダル・ダイアログで、フォーム上部のタイトル・バーにある[×]ボタン(=[閉じる]ボタン)をクリックしてダイアログを閉じた場合、DialogオブジェクトのDialogResultプロパティには「DialogResult.Cancel」が固定的に設定される。

モードレス・ダイアログを表示するには?

 作成したダイアログをモードレス・ダイアログとして起動するには、DialogオブジェクトのShowメソッドを呼び出せばよい。なお、モードレス・ダイアログのShowメソッドは、モーダル・ダイアログのShowDialogメソッドと違い、ダイアログを表示して(ダイアログが閉じられないままの状態で)すぐにメソッド呼び出しが完了するので注意が必要だ。

 以下にそのコードを示す。

private void button1_Click(object sender, System.EventArgs e)
{
  // モードレス・ダイアログを表示する
  TestDlg dlg = new TestDlg();
  dlg.Owner = this;
  dlg.Show();      // ダイアログを表示する
  // dlg.Close;    // ダイアログを閉じる
}

モードレス・ダイアログを表示するサンプル・コード
サンプル・プログラム(C#:dialog3.cs、VB.NET:dialog3.vb)のダウンロード
ダイアログを表示するフォームをダイアログのオーナー(所有者)に指定するには、ダイアログのOwnerプロパティにフォームのオブジェクトを指定すればよい。これによりフォームよりも後ろにダイアログが表示されなくなる。

 なお、フォームから強制的にダイアログを閉じるには、DialogオブジェクトのCloseメソッドを呼び出せばよい。

 また、モードレス・ダイアログの場合、DaialogオブジェクトのAcceptButtonプロパティやCancelButtonプロパティを設定しても、ダイアログを閉じる処理のコードを記述しないとダイアログを閉じることはできない。そのため、ダイアログ上の[閉じる]ボタンのClickイベント・ハンドラを忘れずに実装する必要があるので、注意していただきたい。

カテゴリ:Windowsフォーム 処理対象:ダイアログ・ボックス
使用ライブラリ:Formクラス(System.Windows.Forms名前空間)
使用ライブラリ:DialogResult列挙体(System.Windows.Forms名前空間)
関連TIPS:メッセージ・ボックスを表示するには?
関連TIPS:[フォルダの参照]ダイアログを使用するには?


■更新履歴

【2005/05/26】本記事の一部に以下のような誤りがありました。お詫びして訂正させていただきます。

誤:ShowDialogメソッドの戻り値は、ダイアログの処理結果を示すためにDialogResultプロパティで設定しておいた値である。このDialogResultプロパティの値には、DialogResult列挙体の値が使われる。

 モーダル・ダイアログの[閉じる]ボタンであるButtonオブジェクトをDialogオブジェクトのAcceptButtonプロパティに設定しておけば、ダイアログが閉じられたあと、ShowDialogメソッドの戻り値としてDialogResult.OKが返されるようになる。この場合には、[閉じる]ボタンのClickイベント・ハンドラを実装する必要がなくなる。[キャンセル]ボタンの場合も同様に、CancelButtonプロパティを設定しておけば、ダイアログが自動的に閉じられたあと、ShowDialogメソッドの戻り値としてDialogResult.Cancelが返されるようになる。ただし、これらのAcceptButtonプロパティやCancelButtonプロパティが有効に機能するのは、モーダル・ダイアログの場合だけである。次に紹介するモードレス・ダイアログでは機能しないので注意が必要である。

正:ShowDialogメソッドの戻り値は、ダイアログの処理結果を示すためのもので、Dialogオブジェクト(=フォーム)のDialogResultプロパティの値である。このDialogResultプロパティの値には、DialogResult列挙体の値が使われる。

 モーダル・ダイアログ上のButtonオブジェクト(本稿の例では、[閉じる]ボタン)を、DialogオブジェクトのAcceptButtonプロパティに設定すれば、ユーザーがフォーム上で[Enter]キーを押したときに、そのボタンのクリック処理が実行されるようになる。また、CancelButtonプロパティを設定しておけば、ユーザーがフォーム上で[Escape]キーを押したときに、そのボタンのクリック処理が実行されるようになる。

 ボタンのDialogResultプロパティに、「DialogResult.Cancel」や「DialogResult.OK」などのDialogResult列挙体の値が設定されている場合、そのボタンがクリックされるとDialogオブジェクトのDialogResultプロパティに対してそのDialogResult列挙体の値が設定される。モーダル・ダイアログでは、DialogオブジェクトのDialogResultプロパティに「DialogResult.None」以外の値が設定されると、自動的にダイアログが終了する仕組みになっている。このため、ボタンのDialogResultプロパティを設定すれば、ボタンのClickイベント・ハンドラでダイアログの終了処理を実装する必要はない(ただし次に紹介するモードレス・ダイアログの場合は、Closeメソッドなどによるダイアログの終了処理が必要となる)。

 なお、DialogオブジェクトのCancelButtonプロパティを設定すると、設定されたボタンのDialogResultプロパティに「DialogResult.Cancel」が自動的に設定される(ただし、この自動設定が行われるのは、ボタンのDialogResultプロパティの値が「DialogResult.None」の場合のときだけだ)。しかし、AcceptButtonプロパティを設定した場合では、設定されたボタンのDialogResultプロパティの値は変更されないので注意してほしい。

 ちなみに、モーダル・ダイアログで、フォーム上部のタイトル・バーにある[×]ボタン(=[閉じる]ボタン)をクリックしてダイアログを閉じた場合、DialogオブジェクトのDialogResultプロパティには「DialogResult.Cancel」が固定的に設定される。

【2004/03/26】初版公開。


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。