DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

メニューにアイコンを表示する

ここでは、メニュー項目にアイコン(画像)を表示する方法を紹介します。MenuStripコントロールの場合と、MainMenuコントロールの場合に分けて説明します。

アイコンが表示されたメニュー

.NET Framework 2.0以降で、MenuStrip(またはContextMenuStrip)コントロールを使用している場合

.NET Framework 2.0以降で、メニューにMenuStripコントロールContextMenuStripコントロールを使用している場合はとても簡単です。メニュー項目のToolStripMenuItem.Imageプロパティに画像を設定して、ToolStripMenuItem.DisplayStyleプロパティを「ImageAndText」(または、「Image」)にするだけです。(DisplayStyleプロパティはデフォルトで「ImageAndText」です。)

ToolStripMenuItem.Imageプロパティを設定

フォームデザイナのプロパティウィンドウを使用してImageプロパティを設定しようとすると、「リソースの選択」ダイアログが表示されます。Imageプロパティに画像ファイルを設定する場合は、ここで「ローカルリソース」を選択してから「インポート」ボタンをクリックし、画像ファイルを選択してください。

「リソースの選択」ダイアログ

補足:このようにしてインポートした画像は、フォームのリソース(resxファイル)に埋め込まれます。よって、インポート元の画像ファイルを編集したり、削除したりしても、メニューの画像は変わりません。画像を変えるには、もう一度画像ファイルをインポートします。なお「プロジェクトリソースファイル」を選択して画像ファイルをインポートした場合は、コンボボックスに表示されているresxファイル(デフォルトでは、C#では「Properties\Resources.resx」、VB.NETでは「My Project\Resources.resx」)に埋め込まれます。

透明色を指定する場合は、ToolStripItem.ImageTransparentColorプロパティを使います。

デフォルト(ToolStripItem.ImageScalingプロパティがSizeToFitの時)では、基の画像の大きさにかかわらず、適当な大きさ(ToolStrip.ImageScalingSizeプロパティで指定された大きさ)に拡大、縮小されて表示されます。ImageScalingプロパティをNoneにすると、画像は拡大、縮小されなくなります。

補足:ここで紹介した方法以外に、ImageListコンポーネントToolStrip.ImageListプロパティ、そしてToolStripItem.ImageIndexプロパティToolStripItem.ImageKeyプロパティを使用して、アイコンを表示することもできます。ただしこの方法はフォームデザイナでは行うことができませんので、ToolStrip.ImageListプロパティとToolStripItem.ImageIndexプロパティ(またはImageKeyプロパティ)の設定は自分でコードを書いて行う必要があります。

.NET Framework 1.1以前で、MainMenu(またはContextMenu)コントロールを使用している場合

.NET Framework 1.1以前ではMainMenuコントロール(または、ContextMenuコントロール)を使うしかありませんが、簡単にアイコンを表示する方法は用意されていません。そこでここでは、オーナードローによりMainMenuにアイコンを表示する方法を紹介します。

メニューにアイコンを表示するにはオーナードローを行います。オーナードローとは、コントロールの描画をOS等に任せるのではなく、自分でコードを書いて行うということです。

ここでは、メニューにアイコンを表示するためにはどのようなことを行えばいいのかというごく簡単な例のみを示します。この例はメニューアイテムが無効になっているときや、チェックが付いているとき、セパレータのときなどを全く考慮してないため実用には程遠いですが、参考にはなると思います。なお実際にはMenuItemクラスから派生させた新しいクラスを作成し、使用するとよいでしょう(そのようなクラスをこちらで紹介しています)。

メニューにアイコンを表示

以下にその手順を示します。

1.フォーム(Form1)にMainMenuコントロール(MainMenu1)を貼り付ける。

2.MainMenu1にMenuItemを一つ追加し(MenuItem1)、Textを「ファイル(&F)」とする。

3.MenuItem1の下に新しいMenuItemを追加し(MenuItem2)、Textを「新規作成(&N)」、Shuortcutを「CtrlN」とする。この左側にアイコンを表示するようにする。

4.MenuItem2のOwnerDrawプロパティをTrueにする。

5.MenuItem2のMeasureItemイベントハンドラ(MenuItem2_MeasureItem)と、DrawItemイベントハンドラ(MenuItem2_DrawItem)を作成し、次のようなコードを書く。

VB.NET
コードを隠すコードを選択
'メニューに表示するアイコンをあらかじめ読み込んでおく
Private newIcon As New Icon("new.ico")

Private Sub MenuItem2_MeasureItem(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MeasureItemEventArgs) _
    Handles MenuItem2.MeasureItem
    'メニューアイテムの大きさを計算する
    '高さを"e.ItemHeight"に幅を"e.ItemWidth"に入れる

    Dim mi As MenuItem = CType(sender, MenuItem)

    'メニューに表示する文字列を取得
    Dim menuText As String
    menuText = mi.Text
    If mi.ShowShortcut AndAlso mi.Shortcut <> Shortcut.None Then
        'ショートカットを表示するときは、その文字列を追加する
        menuText += " " + _
            System.ComponentModel.TypeDescriptor.GetConverter( _
            GetType(Keys)).ConvertToString(CType(mi.Shortcut, Keys))
    End If
    Dim sf As New StringFormat()
    'ホットキープリフィックスの表示(&を_にする)
    sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show
    '幅を決定する
    '文字列の幅にアイコンの幅16と余白30を足す
    e.ItemWidth = CInt(e.Graphics.MeasureString(menuText, _
        SystemInformation.MenuFont, Integer.MaxValue, sf).Width + 46)
    'リソースを解放
    sf.Dispose()

    '高さを決定する(19bitに固定する)
    e.ItemHeight = 19
End Sub

Private Sub MenuItem2_DrawItem(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.DrawItemEventArgs) _
    Handles MenuItem2.DrawItem
    'メニューアイテムを描く

    Dim mi As MenuItem = CType(sender, MenuItem)

    Dim b As Brush
    If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
        '選択されている時
        '背景を塗りつぶす
        e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds)
        '文字列の描画に使用するブラシの作成
        b = New SolidBrush(SystemColors.HighlightText)
    Else
        '選択されていない時
        '背景を塗りつぶす
        e.Graphics.FillRectangle(SystemBrushes.Menu, e.Bounds)
        '文字列の描画に使用するブラシの作成
        b = New SolidBrush(SystemColors.MenuText)
    End If

    'アイコンを描く
    e.Graphics.DrawIcon(newIcon, e.Bounds.Left + 2, _
        e.Bounds.Top + (e.Bounds.Height - newIcon.Height) \ 2)

    '文字を描画
    Dim sf As New StringFormat()
    'ホットキープリフィックスの表示(&を_にする)
    sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show
    'Text部分を描画
    Dim top As Integer = _
        (e.Bounds.Height - SystemInformation.MenuFont.Height) \ 2
    e.Graphics.DrawString(mi.Text, SystemInformation.MenuFont, _
        b, e.Bounds.Left + 22, e.Bounds.Top + top, sf)
    If mi.ShowShortcut AndAlso mi.Shortcut <> Shortcut.None Then
        'Shortcut部分を描画
        'Shortcut部分の文字列を取得
        Dim shortcutText As String = _
            System.ComponentModel.TypeDescriptor.GetConverter( _
            GetType(Keys)).ConvertToString(CType(mi.Shortcut, Keys))
        'Shortcut部分の幅を取得
        Dim shortcutWidth As Integer = _
            CInt(e.Graphics.MeasureString(shortcutText, _
            SystemInformation.MenuFont, Integer.MaxValue, sf).Width)
        'Shortcut部分の文字列を描画
        e.Graphics.DrawString(shortcutText, SystemInformation.MenuFont, _
            b, e.Bounds.Right - shortcutWidth - 24, _
            e.Bounds.Top + top, sf)
    End If

    'リソースを解放
    b.Dispose()
    sf.Dispose()
End Sub
C#
コードを隠すコードを選択
//メニューに表示するアイコンをあらかじめ読み込んでおく
private Icon newIcon = new Icon("new.ico");

private void MenuItem2_MeasureItem(object sender,
    System.Windows.Forms.MeasureItemEventArgs e)
{
    //メニューアイテムの大きさを計算する
    //高さを"e.ItemHeight"に幅を"e.ItemWidth"に入れる

    MenuItem  mi = (MenuItem) sender;

    //メニューに表示する文字列を取得
    string menuText;
    menuText = mi.Text;
    if (mi.ShowShortcut && mi.Shortcut != Shortcut.None)
    {
        //ショートカットを表示するときは、その文字列を追加する
        menuText += " " +
            System.ComponentModel.TypeDescriptor.GetConverter(
            typeof(Keys)).ConvertToString((Keys) mi.Shortcut);
    }
    StringFormat sf = new StringFormat();
    //ホットキープリフィックスの表示(&を_にする)
    sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
    //幅を決定する
    //文字列の幅にアイコンの幅16と余白30を足す
    e.ItemWidth = (int) e.Graphics.MeasureString(menuText,
        SystemInformation.MenuFont, int.MaxValue, sf).Width + 46;
    //リソースを解放
    sf.Dispose();

    //高さを決定する(19bitに固定する)
    e.ItemHeight = 19;
}

private void MenuItem2_DrawItem(object sender,
    System.Windows.Forms.DrawItemEventArgs e)
{
    //メニューアイテムを描く

    MenuItem  mi= (MenuItem) sender;

    Brush b;
    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
    {
        //選択されている時
        //背景を塗りつぶす
        e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
        //文字列の描画に使用するブラシの作成
        b = new SolidBrush(SystemColors.HighlightText);
    }
    else
    {
        //選択されていない時
        //背景を塗りつぶす
        e.Graphics.FillRectangle(SystemBrushes.Menu, e.Bounds);
        //文字列の描画に使用するブラシの作成
        b = new SolidBrush(SystemColors.MenuText);
    }

    //アイコンを描く
    e.Graphics.DrawIcon(newIcon, e.Bounds.Left + 2,
        e.Bounds.Top + (e.Bounds.Height - newIcon.Height) / 2);

    //文字を描画
    StringFormat sf = new StringFormat();
    //ホットキープリフィックスの表示(&を_にする)
    sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
    //Text部分を描画
    int  top=
        (e.Bounds.Height - SystemInformation.MenuFont.Height) / 2;
    e.Graphics.DrawString(mi.Text, SystemInformation.MenuFont,
        b, e.Bounds.Left + 22, e.Bounds.Top + top, sf);
    if (mi.ShowShortcut && mi.Shortcut != Shortcut.None)
    {
        //Shortcut部分を描画
        //Shortcut部分の文字列を取得
        string  shortcutText=
            System.ComponentModel.TypeDescriptor.GetConverter(
            typeof(Keys)).ConvertToString((Keys) mi.Shortcut);
        //Shortcut部分の幅を取得
        int  shortcutWidth=
            (int) e.Graphics.MeasureString(shortcutText,
            SystemInformation.MenuFont, int.MaxValue, sf).Width;
        //Shortcut部分の文字列を描画
        e.Graphics.DrawString(shortcutText, SystemInformation.MenuFont,
            b, e.Bounds.Right - shortcutWidth - 24,
            e.Bounds.Top + top, sf);
    }

    //リソースを解放
    b.Dispose();
    sf.Dispose();
}
  • 履歴:
  • 2007/1/15 「.NET Framework 2.0以降で、MenuStripを使用する」を追加。
  • 2014/5/26 MenuStripに画像を表示する方法の説明をより詳しく書き直した。
  • 2014/9/29 「リソースの選択」ダイアログに関する説明を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。