コンテキストメニューは、通常のメニューと作り方はほとんど同じです。
違う点は、FormのContextMenuプロパティにContextMenuオブジェクトを設定する点です。
public virtual ContextMenu ContextMenu { get; set; }プロパティ値は、ContextMenuオブジェクトです。
ContextMenuクラスの継承関係は次のようになっています。
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Menu System.Windows.Forms.ContextMenuコンストラクタは、オーバーロードされた2つのバージョンがあります。
public ContextMenu () public ContextMenu ( MenuItem[] menuItems )menuItemsは、MenuItemオブジェクトの配列です。
では、実際のプログラムを見てみましょう。
// contextmenu01.cs using System; using System.Drawing; using System.Windows.Forms; class contextmenu01 { public static void Main() { MyForm mf = new MyForm(); Application.Run(mf); } } class MyForm : Form { string strTitle; public MyForm() { strTitle = "猫でもわかるプログラミング"; Text = strTitle; BackColor = SystemColors.Window; ContextMenu cm = new ContextMenu(); ContextMenu = cm; MenuItem miFile = new MenuItem("ファイル(&F)"); cm.MenuItems.Add(miFile); MenuItem miOpen = new MenuItem("開く(&O)"); miOpen.Shortcut = Shortcut.CtrlO; miOpen.Click += new EventHandler(miOpen_Click); miFile.MenuItems.Add(miOpen); MenuItem miLine = new MenuItem("-"); miFile.MenuItems.Add(miLine); MenuItem miExit = new MenuItem("終了(&X)"); miExit.Click += new EventHandler(miExit_Click); miFile.MenuItems.Add(miExit); } void miExit_Click(object sender, EventArgs e) { Close(); } void miOpen_Click(object sender, EventArgs e) { MessageBox.Show("「開く」が選択されました", strTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); } protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); DialogResult dr; dr = MessageBox.Show("終了してもよろしいですか", strTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (dr == DialogResult.Yes) e.Cancel = false; else e.Cancel = true; } }このプログラムでは、まず
ContextMenu cm = new ContextMenu();として、メニュー項目を持たないコンテキストメニュー・オブジェクトを作成し、
ContextMenu = cm;のように、フォームのContextプロパティに設定しています。
この後は、MenuItems.Addメソッドでメニュー項目を継ぎ足していっています。
ここで、ちょっと注意する点は、
MenuItem miLine = new MenuItem("-"); miFile.MenuItems.Add(miLine);です。これは、「-」というメニュー項目を作っているわけではありません。メニュー項目のテキストを「-」にすると実際に表示されるのは区切り線です。
メニューの「終了」が選択されると、miExit_Clickメソッドが呼び出されます。ここで、 Closeメソッドを呼び出して、フォームをクローズしてプログラムを終了しています。
しかし、いきなり終了してはまずいときは、途中でこれを中止する仕組みが必要です。
フォームが閉じる前に、Form.FormClosingイベントが発生します。これを捕まえて閉じるのを阻止すればよいですね。
このイベントはC#2.0から追加されたものです。それまでは、Closingイベントが使われていました。C#2.0では、もはや使われません。(注:C#2.0でも互換性からプログラムで使うことは可能です。)
こういった基本的仕様がチョコチョコ変更されるのは好ましくないと筆者は思いますが、いかがなものでしょうか。
さて、FormClosingイベントを捕まえるには、OnFormClosingメソッドをオーバーライドします。
protected virtual void OnFormClosing ( FormClosingEventArgs e )そして、FormClosingEventArgsクラスのCancelプロパティをtrueに設定します。これで、フォームは何事もなかったようになります。
さて、第8章で、Applicatin.Exitメソッドについて少し触れました。このメソッドを実行してもフォームは閉じてプログラムは終了します。しかし、今は使われていないClosingイベントは発生しません。(FormColsingイベントは発生する)
では、実行結果を見てみましょう。
クライアント領域を右クリックすると、メニューが出てきます。
「開く」と「終了」の間に区切り線があることに注意してください。
ここで、「終了」を選択します。すると・・・
終了してもよいか、確認のメッセージボックスが出てきます。
ここで、ちょっと注意すべき点は、デフォルトのボタン(点線でキャプションが囲まれている)が「いいえ」になっている点です。
これは、MessageBox.Showメソッドの5番目の引数をMessageBoxDefaultButton.Button2として2番目のボタン「いいえ」をデフォルトボタンに指定しているからです。
Update 07/Nov/2006 By Y.Kumei