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

ToolStrip(ツールバー、メニュー、ステータスバー)やToolStripContainerの外観を変更する

注意:ここで紹介している方法は、.NET Framework 2.0以降でのみ使用できます。

ToolStripやToolStripContainer(以下まとめてToolStripとする)の外観を変更するための方法として、RenderModeプロパティRendererプロパティが用意されています。

RenderModeプロパティで手軽に変更する

まずは、Visual Studioのフォームデザイナを使って、手軽に外観を変更させてみましょう。

ToolStripやToolStripContentPanel、ToolStripPanelコントロールには、RenderModeプロパティが用意されており、フォームデザイナでこの値を変更することができます。

RenderModeプロパティの値はデフォルトでManagerRenderModeですが、SystemかProfessionalに変更することができます(.NET Framework 4.5現在)。RenderModeプロパティをSystemに変更すると、地味な(システムカラーとフラットなvisualスタイルを使用した)外観になります。Professionalに変更すると、Microsoft Officeのような外観になります。

以下の画像は、RenderModeプロパティをSystemにした時のものです。

ToolStrip

すべてのToolStripの外観を変更する

RenderModeプロパティはデフォルトでManagerRenderModeですが、これは何でしょうか?実は、RenderModeプロパティがManagerRenderModeの時は、静的プロパティであるToolStripManager.RenderModeToolStripManager.Rendererプロパティが使われます。つまり、RenderModeプロパティがManagerRenderModeとなっているすべてのToolStrip(及び、ToolStripContentPanel、ToolStripPanel)には、ToolStripManager.RenderModeとRendererプロパティの設定が使われます。逆に言えば、、ToolStripManager.RenderModeあるいはRendererの値を変更することにより、アプリケーション内のすべてのToolStripの外観を一度に変更することができるということです。

試しに、次のようなコードを実行してみてください。RenderModeがManagerRenderModeのすべてのToolStrip、ToolStripContentPanel、ToolStripPanelの外観がSystemに変更されることでしょう。

VB.NET
コードを隠すコードを選択
ToolStripManager.RenderMode = ToolStripManagerRenderMode.System
C#
コードを隠すコードを選択
ToolStripManager.RenderMode = ToolStripManagerRenderMode.System;

ToolStripManager.Rendererプロパティを使って、すべてのToolStripの外観を変更する

もっと細かくToolStripの外観をカスタマイズするには、Rendererプロパティを設定することになります。そのためには、ToolStripRendererクラスを継承したクラスを作成して、どのように描画するかをすべて指定しなければなりません(具体的な方法は、後述します)。

ただ、これはあまりに面倒です。そこで、.NET Framework 2.0では、ToolStripRendererを継承した2つのクラス、ToolStripSystemRendererToolStripProfessionalRendererクラスがあらかじめ用意されています。

実は、RenderModeプロパティをSystemにするとRendererにToolStripSystemRendererを使い、ProfessionalにするとToolStripProfessionalRendererを使うということなのです。つまり、先ほどのToolStripManager.RenderModeをSystemにするというコードは、次のようなコードであっても、外観がどうなるかという結果に関しては、全く同じになります。

VB.NET
コードを隠すコードを選択
ToolStripManager.Renderer = New ToolStripSystemRenderer()
C#
コードを隠すコードを選択
ToolStripManager.Renderer = new ToolStripSystemRenderer();

ProfessionalColorTableクラスでグラデーションを変更する

ToolStripProfessionalRendererクラスには、ToolStripの外観の色を変更するための、簡単で面白い方法が用意されています。RenderModeがProfessionalの時は、Microsoft Officeのような、グラデーションのかかったカッコいい見た目になりますが、どのような色でグラデーションをかけるかを簡単に変更することができるのです。

そのためには、ProfessionalColorTableクラスを継承したクラスを作成し、ここでグラデーションのかけ方を指定し、このオブジェクトを指定して、ToolStripProfessionalRendererオブジェクトを作成します。

まずは例をご覧ください。はじめにProfessionalColorTableクラスを継承したCustomProfessionalRendererクラスを作成します。ここでは、ToolStripとToolStripPanelの色だけを変更しています。

VB.NET
コードを隠すコードを選択
Public Class CustomProfessionalRenderer
    Inherits ProfessionalColorTable

    'ToolStripのグラデーションの色を指定
    Public Overrides ReadOnly Property ToolStripGradientBegin() As Color
        Get
            Return Color.WhiteSmoke
        End Get
    End Property

    Public Overrides ReadOnly Property ToolStripGradientMiddle() As Color
        Get
            Return Color.LightGray
        End Get
    End Property

    Public Overrides ReadOnly Property ToolStripGradientEnd() As Color
        Get
            Return Color.Gray
        End Get
    End Property

    'ToolStripPanelのグラデーションの色を指定
    Public Overrides ReadOnly Property ToolStripPanelGradientBegin() As Color
        Get
            Return Color.Gold
        End Get
    End Property

    Public Overrides ReadOnly Property ToolStripPanelGradientEnd() As Color
        Get
            Return Color.Ivory
        End Get
    End Property
End Class
C#
コードを隠すコードを選択
using System.Windows.Forms;
using System.Drawing;

public class CustomProfessionalRenderer : ProfessionalColorTable
{
    //ToolStripのグラデーションの色を指定
    public override Color ToolStripGradientBegin
    {
        get
        {
            return Color.WhiteSmoke;
        }
    }

    public override Color ToolStripGradientMiddle
    {
        get
        {
            return Color.LightGray;
        }
    }

    public override Color ToolStripGradientEnd
    {
        get
        {
            return Color.Gray;
        }
    }

    //ToolStripPanelのグラデーションの色を指定
    public override Color ToolStripPanelGradientBegin
    {
        get
        {
            return Color.Gold;
        }
    }

    public override Color ToolStripPanelGradientEnd
    {
        get
        {
            return Color.Ivory;
        }
    }
}

ToolStripGradientBegin、ToolStripGradientMiddle、ToolStripGradientEndプロパティでToolStripにグラデーションの開始色、中間色、終了色を指定し、ToolStripPanelGradientBeginとToolStripPanelGradientEndでToolStripPanelにグラデーションの開始色と終了色を指定します。

このCustomProfessionalRendererを使って実際にToolStripとToolStripPanelの外観を変更するには、次のようにします。

VB.NET
コードを隠すコードを選択
'アプリケーション全体にカスタムのプロフェッショナルレンダラを適用する
ToolStripManager.Renderer = _
    New ToolStripProfessionalRenderer(New CustomProfessionalRenderer())
C#
コードを隠すコードを選択
//アプリケーション全体にカスタムのプロフェッショナルレンダラを適用する
ToolStripManager.Renderer =
    new ToolStripProfessionalRenderer(new CustomProfessionalRenderer());

上記の例では、見た目が次のように変化します。

ToolStrip

個々のToolStripやToolStripPanelのみを変更するのであれば、そのコントロールのRendererにToolStripProfessionalRendererオブジェクトを設定してください。

補足:Rendererにカスタムレンダラを設定すると、RenderModeプロパティは自動的にCustomとなります。

ProfessionalColorTableに関する補足

私がProfessionalColorTableを使ってみて気が付いた点を以下に挙げます。

ToolStripGradientMiddleを指定しないと、デフォルトの色が使われるようですので、ToolStripGradientBeginとToolStripGradientEndを変更するならば、ToolStripGradientMiddleも変更しないと、意図した色にならないでしょう。(しかし、ButtonSelectedGradientMiddleやMenuItemPressedGradientMiddleなど、...Middleの他のメソッドは、指定しても無視されました。)

グラデーションの方向に関しては、MSDNに何の説明もありません。そこで私が実際に試して調べた結果を記述しておきます。

ToolStripGradientBegin、ToolStripGradientMiddle、ToolStripGradientEndによるToolStripのグラデーションでは、ToolStripが横長(LayoutStyleがHorizontalStackWithOverflow)の時は、左から右へのグラデーションとなり、ToolStripが縦長(LayoutStyleがVerticalStackWithOverflow)の時は、上から下へのグラデーションとなります。

ToolStripPanelGradientBegin、ToolStripPanelGradientEndによるToolStripPanelのグラデーションでは、左から右へのグラデーションとなります。しかし、必ずしもToolStripPanelの左端がToolStripPanelGradientBeginで指定した色で、右端がToolStripPanelGradientEndで指定した色とはならず、その間の一部分のようにグラデーションがかかります。

MenuStripのMenuStripGradientBegin、MenuStripGradientEndでは、MenuStripが横長の場合に、左から右へのグラデーションとなります。縦長の場合は、グラデーションとならず、MenuStripGradientBeginで指定した一色のみとなるようです。

MenuItemPressedGradientBegin、MenuItemPressedGradientEndなど、MenuItemの場合は、上から下へのグラデーションとなります。(なお、MenuItemPressedGradient...やMenuItemSelectedGradient...は、ToolStripComboBoxの下矢印ボタンにも使用されます。)

OverflowButtonGradientBegin、OverflowButtonGradientEndによるオーバーフローボタンは、MenuStripが横長の場合は上から下、横長の場合は左から右のグラデーションとなります。(なお、ToolStripOverflowButtonの選択時や、押した時の色は、ButtonSelectedGradient...やButtonPressedGradient...が使用されます。)

ToolStripContainerのContentPanelのRendererはグラデーションとならず、ToolStripContentPanelGradientEndで指定した一色となりました。

また、RaftingContainerGradientBeginとRaftingContainerGradientEndは全く無視され、どのようにすれば有効になるのか分かりませんでした。

カスタムToolStripRendererを作成して、細かい変更をする

さらに細かくToolStripの外観を指定したい場合は、ToolStripRendererクラスの派生クラスを独自に作成し、ToolStripをどのように描画するかを指定します。

ToolStripRendererクラスは抽象クラスですので、必ず派生クラスを作成する必要があります。抽象メンバはありませんので、必ずオーバーライドしなければならないメンバはありませんが、そのままでは画像やテキストが表示されるだけで、使い物になりません。もしToolStripRendererクラスを直接継承するのであれば、多くのメソッドをオーバーライドする必要があるでしょう。

もしToolStripSystemRendererやToolStripProfessionalRendererを基にして、その一部分の描画を変更するだけであれば、これらのクラスを継承して、適当なメソッドをオーバーライドするだけでよいので、簡単です。

以下に、ToolStripProfessionalRendererを継承して、OnRenderToolStripBackgroundとOnRenderButtonBackgroundをオーバーライドすることにより、ToolStripの背景とToolStripButtonの背景を独自に描画する例を示します。

VB.NET
コードを隠すコードを選択
Imports System.Windows.Forms
Imports System.Drawing

Public Class CustomRenderer
    Inherits ToolStripProfessionalRenderer

    'ToolStripの背景を描画
    Protected Overrides Sub OnRenderToolStripBackground( _
        ByVal e As ToolStripRenderEventArgs)
        Dim b As New SolidBrush(Color.LightGray)
        e.Graphics.FillRectangle(b, e.AffectedBounds)
        b.Dispose()
    End Sub

    'ToolStripButtonの背景を描画
    Protected Overrides Sub OnRenderButtonBackground( _
        ByVal e As ToolStripItemRenderEventArgs)
        Dim btn As ToolStripButton = CType(e.Item, ToolStripButton)

        Dim b As SolidBrush
        If btn.Pressed Or btn.Checked Then
            'ボタンが押されている時
            b = New SolidBrush(Color.LightSalmon)
        Else
            If btn.Selected Then
                'ボタンが選択されている時
                b = New SolidBrush(Color.Aquamarine)
            Else
                'ボタンが普通の状態の時
                b = New SolidBrush(Color.Silver)
            End If
        End If
        'ボタンの背景を描画する
        e.Graphics.FillRectangle(b, btn.ContentRectangle)
        b.Dispose()
    End Sub
End Class
C#
コードを隠すコードを選択
using System.Windows.Forms;
using System.Drawing;

public class CustomRenderer : ToolStripProfessionalRenderer
{
    //ToolStripの背景を描画
    protected override void OnRenderToolStripBackground(
        ToolStripRenderEventArgs e)
    {
        SolidBrush b = new SolidBrush(Color.LightGray);
        e.Graphics.FillRectangle(b, e.AffectedBounds);
        b.Dispose();
    }

    //ToolStripButtonの背景を描画
    protected override void OnRenderButtonBackground(
        ToolStripItemRenderEventArgs e)
    {
        ToolStripButton btn = (ToolStripButton)e.Item;

        SolidBrush b;
        if (btn.Pressed || btn.Checked)
        {
            //ボタンが押されている時
            b = new SolidBrush(Color.LightSalmon);
        }
        else if (btn.Selected)
        {
            //ボタンが選択されている時
            b = new SolidBrush(Color.Aquamarine);
        }
        else
        {
            //ボタンが普通の状態の時
            b = new SolidBrush(Color.Silver);
        }
        //ボタンの背景を描画する
        e.Graphics.FillRectangle(b, btn.ContentRectangle);
        b.Dispose();
    }
}

使い方はやはり同じように、たとえば、
ToolStripManager.Renderer = New CustomRenderer()
のようにします。

ToolStrip

ToolStripRendererクラスのイベントを処理して、同様のことを行う

実はこのようなカスタムのToolStripRendererクラスを作成しなくても、ToolStripRendererクラスのイベント(ToolStripRenderer.RenderToolStripBackgroundイベント)を処理することにより、同じことができます。

VB.NET
コードを隠すコードを選択
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)

    Dim proRenderer As New ToolStripProfessionalRenderer()
    AddHandler proRenderer.RenderToolStripBackground, _
        AddressOf proRenderer_RenderToolStripBackground
    ToolStripManager.Renderer = proRenderer
End Sub

Private Sub proRenderer_RenderToolStripBackground( _
    ByVal sender As Object, ByVal e As ToolStripRenderEventArgs)

    Dim b As New SolidBrush(Color.LightGray)
    e.Graphics.FillRectangle(b, e.AffectedBounds)
    b.Dispose()
End Sub
C#
コードを隠すコードを選択
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    ToolStripProfessionalRenderer proRenderer =
        new ToolStripProfessionalRenderer();
    proRenderer.RenderToolStripBackground +=
        new ToolStripRenderEventHandler(proRenderer_RenderToolStripBackground);
    ToolStripManager.Renderer = proRenderer;
}

private void proRenderer_RenderToolStripBackground(
    object sender, ToolStripRenderEventArgs e)
{
    SolidBrush b = new SolidBrush(Color.LightGray);
    e.Graphics.FillRectangle(b, e.AffectedBounds);
    b.Dispose();
}

ToolStripProfessionalRendererでToolStripの角を四角くする

ToolStripProfessionalRendererを使うと、デフォルトではToolStripの角が丸くなりますが、ToolStripProfessionalRenderer.RoundedEdgesプロパティをFalseにすることにより、角を四角くすることができます。ただそれだけです...。

VB.NET
コードを隠すコードを選択
Dim proRenderer As New ToolStripProfessionalRenderer()
proRenderer.RoundedEdges = False
ToolStripManager.Renderer = proRenderer
C#
コードを隠すコードを選択
ToolStripProfessionalRenderer proRenderer =
    new ToolStripProfessionalRenderer();
proRenderer.RoundedEdges = false;
ToolStripManager.Renderer = proRenderer;

ToolStrip

ToolStripのVisualスタイルを無効にする

ToolStripManager.VisualStylesEnabledメソッドをFalseとすることにより、ToolStripのVisualスタイルを無効にできます。

ToolStrip

ただし、カスタムToolStripRendererで描画している場所(今まで紹介してきたように、ProfessionalColorTableクラスや、ToolStripRendererの派生クラスを使ってToolStripの外観を変更した場所)は、VisualStylesEnabledメソッドの影響を受けません。つまり、カスタムToolStripRendererでもVisualStylesEnabledの値が使えるようにするには、VisualStylesEnabledの値を見て自分で描画法を変更するようにする必要があります。

VisualStylesEnabledをFalseにするコードは、以下のようになります。

VB.NET
コードを隠すコードを選択
'Visualスタイルを無効にする
ToolStripManager.VisualStylesEnabled = False
C#
コードを隠すコードを選択
//Visualスタイルを無効にする
ToolStripManager.VisualStylesEnabled = false;
  • 履歴:
  • 2007/1/17 図を入れた。
  • 2014/9/15 説明を少し書き換え。

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

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。