比較のために WIN32 APIによるC言語プログラムで作成したもの を C# に置き換える。
これは互換性のために用意されたものであり、.Net としては後半に述べる MenuStrip を使った方がよい。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { MainMenu mainMenu; public Form1() { MenuItem mi11 = new MenuItem("menu 1.1(&A)"); mi11.Click += new EventHandler(onClick); MenuItem mi12 = new MenuItem("menu 1.2(&B)"); mi12.Click += new EventHandler(onClick); MenuItem mi13 = new MenuItem("menu 1.3(&C)"); mi13.Click += new EventHandler(onClick); MenuItem mi21 = new MenuItem("menu 2.1(&D)"); mi21.Click += new EventHandler(onClick); MenuItem mi22 = new MenuItem("menu 2.2(&E)"); mi22.Click += new EventHandler(onClick); MenuItem mi1 = new MenuItem("Menu 1(&X)"); mi1.MenuItems.AddRange(new MenuItem[] { mi11, mi12, mi13 }); MenuItem mi2 = new MenuItem("Menu 2(&Y)"); mi2.MenuItems.AddRange(new MenuItem[] { mi21, new MenuItem("-"), mi22 }); mainMenu = new MainMenu(); mainMenu.MenuItems.AddRange(new MenuItem[] { mi1, mi2 }); this.Menu = mainMenu; } void onClick(object sender, EventArgs e) { MessageBox.Show(((MenuItem)sender).Text + "が選択されました", "Menu選択"); } }
上のプログラムの実行画面を下に示す。
左が "Menu 1(X)" をクリックし、マウスカーソルを "menu 1.2(B)" の上に置いたときの画面であり、 右が "menu 1.2(B)" をクリックしたとき現れるメッセージボックスを表す。
上のプログラムでは、どのメニュー項目をクリックしても、 同じ onClick関数がコールされるようにしている。 第1引数senderからどのメニュー項目をクリックしたかが分かる。
もちろん、イベント・ハンドラー(コールバック関数)を共用せず、 単独で使用する関数を登録することができる。この場合は sender の判別は要らない。
外見、仕様はC言語の場合とほぼ同じであるが、WinMain関数よりMain関数の方がすっきりしている。 WindowProc関数はC#では裏に隠されているので記述はいらない。 Win32 APIでのメニュー項目の作成は少々複雑なため、C言語の場合、関数を作った。 C#でのメニュー項目の作成はシンプルである。 このような裏方的なプログラムを除けば、メインのロジックは大差がないが、 C#の方がややシンプルと言える。
下図に示すように、 サブメニュー "menu 1.2(B)" に二つの子メニュー "menu 1.2.1(F)" および "menu 1.2.2(G)" を持たせてみよう。 下の右図は"menu 1.2.2(G)"をクリックしたとき表示されるメッセージボックスを示す。
プログラムを下に示す。 孫メニューを作成し、子メニューに登録すればよい。 やり方は子メニューを親メニューに登録する方法と同じである。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { MainMenu mainMenu; public Form1() { MenuItem mi11 = new MenuItem("menu 1.1(&A)"); mi11.Click += new EventHandler(onClick); MenuItem mi12 = new MenuItem("menu 1.2(&B)"); // 孫メニューの作成 MenuItem mi121 = new MenuItem("menu 1.2.1(&F)"); mi121.Click += new EventHandler(onClick); MenuItem mi122 = new MenuItem("menu 1.2.2(&G)"); mi122.Click += new EventHandler(onClick); // 子メニューに登録 mi12.MenuItems.AddRange(new MenuItem[] { mi121, mi122 }); MenuItem mi13 = new MenuItem("menu 1.3(&C)"); mi13.Click += new EventHandler(onClick); MenuItem mi21 = new MenuItem("menu 2.1(&D)"); mi21.Click += new EventHandler(onClick); MenuItem mi22 = new MenuItem("menu 2.2(&E)"); mi22.Click += new EventHandler(onClick); MenuItem mi1 = new MenuItem("Menu 1(&X)"); mi1.MenuItems.AddRange(new MenuItem[] { mi11, mi12, mi13 }); MenuItem mi2 = new MenuItem("Menu 2(&Y)"); mi2.MenuItems.AddRange(new MenuItem[] { mi21, new MenuItem("-"), mi22 }); mainMenu = new MainMenu(); mainMenu.MenuItems.AddRange(new MenuItem[] { mi1, mi2 }); this.Menu = mainMenu; } void onClick(object sender, EventArgs e) { MessageBox.Show(((MenuItem)sender).Text + "が選択されました", "Menu選択"); } }
メニュー項目にチェックマークを付けるのは極めて簡単である。 MenuItemのChecked属性を true にするだけでよい。 例えば上のプログラムに
mi21.Checked = true;を付け加えると、次のように表示される。
このとき、下のようにすると、チェック記号が●印となる。
mi21.Checked = true; mi21.RadioCheck = true;
従来型のメニューにアイコンを付けるのは、ネット情報によれば、簡単ではない。 オーナードローによる方法がネットにあったが、複雑で、好みに合わない。 もう少し、C#に馴染んでから取り組むことにする。
MainMenuの代わりに、MenuStripを使う場合にはメニュー項目にアイコンを付けるのは簡単である。
MenuStripの場合、Visibleプロパティを true/false とすることにより、表示/非表示を切り替えられる。 従来型Menuの場合、ちょっと調べた限りでは、非表示にできなかった。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { MenuStrip menuStrip = new MenuStrip(); public Form1() { ToolStripMenuItem menuFile = new ToolStripMenuItem(); menuFile.Text = "ファイル(&F)"; ToolStripMenuItem menuAcs = new ToolStripMenuItem(); menuAcs.Text = "アクセサリ(&A)"; ToolStripMenuItem mi1 = new ToolStripMenuItem("電卓(&C)"); mi1.Click += new EventHandler(onClick); mi1.Image = Image.FromFile(@"c:\mh\mcc\ico\calc.ico"); ToolStripMenuItem mi2 = new ToolStripMenuItem("時計(&T)"); mi2.Click += new EventHandler(onClick); mi2.Image = Image.FromFile(@"c:\mh\mcc\ico\clock.ico"); ToolStripSeparator tsSep = new ToolStripSeparator(); ToolStripMenuItem miExit = new ToolStripMenuItem("終了(&X)"); miExit.Click += new EventHandler(onExitClick); menuAcs.DropDownItems.AddRange(new ToolStripItem[] { mi1, mi2, tsSep, miExit }); menuStrip.Items.AddRange(new ToolStripItem[] { menuFile, menuAcs }); this.Controls.Add(menuStrip); this.MainMenuStrip = menuStrip; } void onClick(object sender, EventArgs e) { MessageBox.Show(((ToolStripMenuItem)sender).Text + "が選択されました", "Menu選択"); } void onExitClick(object sender, EventArgs e) { this.Close(); } }
マウスの右ボタンをクリックした時現れるメニューをC#ではコンテキスト・メニューという。 Windows C(WIN32 API)では、ポップアップ・メニューと呼んでいる。 ポップアップは分かるが、C#では何故、コンテキスト(文脈)と呼ぶのか調べていない。
メニュー項目の作り方は通常のメニューと同じである。 メニュー・バーへの登録は this.Menu であったが、 コンテキスト・メニューでは this.ContextMenu に登録する。
プログラム例を下に示す。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { public Form1() { MenuItem mi1 = new MenuItem("menu 1(&A)"); mi1.Click += new EventHandler(onClick); MenuItem mi2 = new MenuItem("menu 2(&B)"); mi2.Click += new EventHandler(onClick); MenuItem miSeparator = new MenuItem("-"); MenuItem miExit = new MenuItem("終了(&X)"); miExit.Click += new EventHandler(onExitClick); this.ContextMenu = new ContextMenu(new MenuItem[] { mi1, mi2, miSeparator, miExit }); } void onClick(object sender, EventArgs e) { MessageBox.Show(((MenuItem)sender).Text + "が選択されました", "Menu選択"); } void onExitClick(object sender, EventArgs e) { this.Close(); } }
マウスの右ボタンをクリックしたときの画面を下に示す。
従来型メニューをツールストリップ型メニューに変えた時のプログラムおよび実行画面を下に示す。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); public Form1() { ToolStripMenuItem mi1 = new ToolStripMenuItem("menu 1(&A)"); mi1.Click += new EventHandler(onClick); ToolStripMenuItem mi2 = new ToolStripMenuItem("menu 2(&B)"); mi2.Click += new EventHandler(onClick); ToolStripSeparator tsSep = new ToolStripSeparator(); ToolStripMenuItem miExit = new ToolStripMenuItem("終了(&X)"); miExit.Click += new EventHandler(onExitClick); contextMenuStrip.Items.AddRange(new ToolStripItem[] { mi1, mi2, tsSep, miExit }); this.ContextMenuStrip = contextMenuStrip; } void onClick(object sender, EventArgs e) { MessageBox.Show(((ToolStripMenuItem)sender).Text + "が選択されました", "Menu選択"); } void onExitClick(object sender, EventArgs e) { this.Close(); } }
メニューにツールチップを付けるには、下の例に示すように、 MenuStripのShowItemToolTipsプロパティにtrueをセットして、 ToolStripMenuItemのToolTipTextプロパティにツールチップとして表示する文字列を設定すればよい。
using System; using System.Drawing; using System.Windows.Forms; class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Form form = new Form1(); form.Text = "Menu Test"; // フォームのタイトル Application.Run(form); } } class Form1 : Form { MenuStrip menuStrip = new MenuStrip() { ShowItemToolTips = true }; public Form1() { ToolStripMenuItem menuFile = new ToolStripMenuItem("ファイル(&F)"); menuFile.ToolTipText = "ファイル関連"; ToolStripMenuItem menuAcs = new ToolStripMenuItem("アクセサリ(&A)"); ToolStripMenuItem mi1 = new ToolStripMenuItem("電卓(&C)"); mi1.Click += new EventHandler(onClick); mi1.Image = Image.FromFile(@"c:\mh\mcc\ico\calc.ico"); mi1.ToolTipText = "電卓"; ToolStripMenuItem mi2 = new ToolStripMenuItem("時計(&T)"); mi2.Click += new EventHandler(onClick); mi2.Image = Image.FromFile(@"c:\mh\mcc\ico\clock.ico"); ToolStripSeparator tsSep = new ToolStripSeparator(); ToolStripMenuItem miExit = new ToolStripMenuItem("終了(&X)"); miExit.Click += new EventHandler(onExitClick); menuAcs.DropDownItems.AddRange(new ToolStripItem[] { mi1, mi2, tsSep, miExit }); menuStrip.Items.AddRange(new ToolStripItem[] { menuFile, menuAcs }); this.Controls.Add(menuStrip); this.MainMenuStrip = menuStrip; } void onClick(object sender, EventArgs e) { MessageBox.Show(((ToolStripMenuItem)sender).Text + "が選択されました", "Menu選択"); } void onExitClick(object sender, EventArgs e) { this.Close(); } }
MenuStripの場合には、メニューには文字列だけではなく、テキスト・ボックスなどのコントロールを含めることもできる。
下のプログラムはメイン・メニュー・バーの右端にテキスト・ボックスを追加したものである。 背景色を設定し、サイズも変更している。
ToolStripTextBox menuTextBox = new ToolStripTextBox() { BackColor = Color.LightYellow }; menuTextBox.Alignment = ToolStripItemAlignment.Right; menuTextBox.Size = new Size(190, 25); menuTextBox.Text = "テスト"; MainMenuStrip.Items.Add(menuTextBox);
実際のプログラム画面を下に示す。 画面をフルに使用するため、メニュー・バーの右端にテキスト・ボックスを追加して、 為替レートのあるポートフォリオに対するミックス値(直近15年、10年、5年平均との相対値を%表記)をリアルタイム表示している。 15年、10年平均に比較すると、1%、5% 円安であり、5年平均に比較すると 3% 円高である。