比較のために 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% 円高である。