トップC# > メニュー

メニュー

1.基本メニュー

比較のために 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#の方がややシンプルと言える。

2.階層メニュー

下図に示すように、 サブメニュー "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選択");
    }
}

3.メニュー項目にチェックマークを付ける

メニュー項目にチェックマークを付けるのは極めて簡単である。 MenuItemのChecked属性を true にするだけでよい。 例えば上のプログラムに

 mi21.Checked = true;
を付け加えると、次のように表示される。

このとき、下のようにすると、チェック記号が●印となる。

 mi21.Checked = true;
 mi21.RadioCheck = true;

4.メニュー項目にアイコンを付ける

従来型のメニューにアイコンを付けるのは、ネット情報によれば、簡単ではない。 オーナードローによる方法がネットにあったが、複雑で、好みに合わない。 もう少し、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();
    }

}

5.コンテキスト・メニュー

マウスの右ボタンをクリックした時現れるメニューを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();
    }
}

マウスの右ボタンをクリックしたときの画面を下に示す。

6.コンテキスト・メニュー(ツールストリップ版)

従来型メニューをツールストリップ型メニューに変えた時のプログラムおよび実行画面を下に示す。

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();
    }

}

7.メニューにツールチップを付ける

メニューにツールチップを付けるには、下の例に示すように、 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();
    }
}

8.メニューにテキスト・ボックスを付ける

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% 円高である。