コンテキストメニューとはWindowsで右クリックすると表示されるメニューのことです。コンテクストとは「文脈」や「状況」のことで、選択していたものや作業状態によって、メニューに表示される項目が切り替わることを意味します。だから同じ右クリックでも場所によって異なるメニューを表示させることができます。
C#なら簡単にコンテキストメニューを表示させ、ユーザーがメニューを選択するとそれに対応した処理をおこなうことができます。
デザイナを使う方法
C# WindowsFormsアプリケーションを作るのであればWindows フォームデザイナーという便利なものがあります。これをつかってコンテキストメニューを表示させる方法を紹介します。
まずツールボックスからContextMenuStripをフォームのうえにドラッグアンドドロップします。
すると以下のようになります。通常のメニューが表示される位置にContextMenuStripが表示されます。他の部分をクリックしてしまうと通常のメニューが表示される位置に表示されていたContextMenuStripは見えなくなってしまいますが、その場合はフォームの下に表示されているcontextMenuStrip1(下の図の下の赤枠で囲まれている部分)を選択すると再度表示されます。
ここへ入力と書かれている部分(上の図の上の赤枠で囲まれている部分)にメニューの項目名を書きます。ここでは「メニューその1」「メニューその2」という項目を追加しました。すると以下の画像のようになります。
メニューをクリックしたらなにをしたいのかを定義します。そのためにはContextMenuStripのメニューの項目が表示されている部分(上の図の赤枠で囲まれている部分)をダブルクリックします。すると以下のようなコードが自動生成されます。
1 2 3 4 5 6 |
public partial class Form1 : Form { private void メニューその1ToolStripMenuItem_Click(object sender, EventArgs e) { } } |
ここでは単純にメニューがクリックされたらMessageBoxを表示させるだけにします。
1 2 3 4 5 6 7 |
public partial class Form1 : Form { private void メニューその1ToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("メニューその1が選択されました"); } } |
イベントハンドラ名に日本語が入ってしまうのはよくないというのであればダブルクリックするまえにContextMenuStripのメニューの項目を選択してプロパティの(Name)の部分を書き換えます。ここではSecondMenuItemという名前に書き換えています(下の図の赤枠で囲まれている部分)。そしてこれをダブルクリックすると以下のようなコードが自動生成されます。
1 2 3 4 5 6 7 |
public partial class Form1 : Form { private void SecondMenuItem_Click(object sender, EventArgs e) { // ここにやりたいことを書く } } |
さてこれだけでは右クリックしてもコンテキストメニューは表示されません。なにを右クリックしたらコンテキストメニューが表示されるのかを指定していないからです。
もしフォームを右クリックしたときにコンテキストメニューが表示されるようにしたいのであればForm1クラスのコンストラクタに以下の1行を追加します。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.ContextMenuStrip = this.contextMenuStrip1; // これを追加する } } |
これで右クリックしたときにコンテキストメニューが表示されますが、なにか物足りないです。多くのアプリケーションはメニューの左側にアイコンが表示されます。ではコンテキストメニューにアイコンを表示させるためにはどうすればいいのでしょうか?
まずアイコンを用意します。アイコンがないなら普通の画像ファイルでもかまいません。
そしてアイコンを設定したいメニューを選択してプロパティのImageの右側をクリックします。
すると下の図のようなダイアログが現れるので、プロジェクトリソースファイルを選択してインポートをクリックします。
インポートしたい画像ファイルを選びます。icoファイルやpng,jpeg,bmpファイルを選択できます。複数選択可なのでインポートしたい画像ファイルを選んだら[開く]を選択します。
インポートされたイメージからメニューのアイコンにしたいものを選択して[OK]をクリックします。
デザイナを使わない方法
デザイナを使わない方法も紹介します。メニューの項目が固定ではなく変化する場合はこちらのほうがいいかもしれません。
ContextMenuStripのインスタンスを生成してForm1.ContextMenuStripプロパティにセットし、あとはContextMenuStrip.Items.Addメソッドで項目を追加します。ContextMenuStrip.Items.Addメソッドにはオーバーロードがいくつかありますが、引数が3つ(string型、Image型、EventHandler型)のものがわかりやすいと思います。
そのときにメニューにアイコンをつけたい場合は、アイコンまたは画像ファイルをリソースに追加しておき、それを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); this.ContextMenuStrip = contextMenuStrip; contextMenuStrip.Items.Add("メニューその1", Properties.Resources.icon1, FirstMenuItem_Click); contextMenuStrip.Items.Add("メニューその2", Properties.Resources.icon2, SecondMenuItem_Click); } private void FirstMenuItem_Click(object? sender, EventArgs e) { MessageBox.Show("メニューその1が選択されました"); } private void SecondMenuItem_Click(object? sender, EventArgs e) { MessageBox.Show("メニューその2が選択されました"); } } |
右クリックされた場所でコンテキストメニューを変える
右クリックされた場所でコンテキストメニューを変えるアプリをつくってみましょう。ContextMenuStripを2つ作り、右クリックした座標がフォームの左半分と右半分で切り替えて表示させます。
フォーム上にLabelを貼り付けておき、メニューがクリックされたら項目名を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public partial class Form1 : Form { ContextMenuStrip _leftContextMenuStrip = new ContextMenuStrip(); ContextMenuStrip _rightContextMenuStrip = new ContextMenuStrip(); public Form1() { InitializeComponent(); _leftContextMenuStrip.Items.Add("Menu 1", Properties.Resources.icon1, MenuItem_Click); _leftContextMenuStrip.Items.Add("Menu 2", Properties.Resources.icon2, MenuItem_Click); _rightContextMenuStrip.Items.Add("メニュー 壱", Properties.Resources.icon3, MenuItem_Click); _rightContextMenuStrip.Items.Add("メニュー 弐", Properties.Resources.icon4, MenuItem_Click); label1.Text = ""; // 最初はなにも表示しない } private void MenuItem_Click(object? sender, EventArgs e) { // sender を ToolStripMenuItem にキャストして Text プロパティを調べるとメニューの項目名がわかる ToolStripMenuItem? item = (ToolStripMenuItem?)sender; if (item != null) label1.Text = item.Text + " が選択されました"; } } |
マウスが移動するとOnMouseMoveが呼び出されます。フォーム上におけるマウスのX座標を調べてフォームの幅の半分未満なら左半分、そうでないなら右半分にマウスポインタがあると判断します。そしてForm1.ContextMenuStripプロパティに適切なContextMenuStripのインスタンスを設定します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { protected override void OnMouseMove(MouseEventArgs e) { if (e.X < this.Width / 2) this.ContextMenuStrip = _leftContextMenuStrip; else this.ContextMenuStrip = _rightContextMenuStrip; base.OnMouseMove(e); } } |
実際に動作させてみるとこんな感じになります。