• 追加された行はこの色です。
  • 削除された行はこの色です。
*.NETプログラミング研究 第67号 [#a75560e4]

**.NET Tips [#cc475534]

今回も前回に引き続き、ToolStripとToolStripContainerに関するTipsを紹介します。

***ToolStripやToolStripContainerの外観を変更する [#ac8585b8]

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

***RenderModeプロパティ [#gebb0541]

まずは、VS2005のデザイナを使って、手軽に外観を変更させてみましょう。

ToolStripやToolStripContentPanel、ToolStripPanelコントロールには、RenderModeプロパティが用意されており、デザイナでこの値を変更することができます。RenderModeプロパティをSystemに変更すると、MS Office XPのような外観だったものが、エクスプローラのような地味な外観に変化するのが分かるでしょう。このように、RenderModeプロパティをSystemにするとエクスプローラのような外観になり、ProfessionalにするとMS Office XPのような外観になります。

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

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

#code(vbnet){{
ToolStripManager.RenderMode = ToolStripManagerRenderMode.System
}}

#code(csharp){{
ToolStripManager.RenderMode = ToolStripManagerRenderMode.System;
}}

[[ToolStripManager.RenderMode プロパティ>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstripmanager.rendermode.aspx]]
-[[ToolStripManager.RenderMode プロパティ>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstripmanager.rendermode.aspx]]

***Rendererプロパティ [#y0918f4b]

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

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

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

#code(vbnet){{
ToolStripManager.Renderer = New ToolStripSystemRenderer()
}}

#code(csharp){{
ToolStripManager.Renderer = new ToolStripSystemRenderer();
}}

[[ToolStripManager.Renderer プロパティ>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstripmanager.renderer.aspx]]
-[[ToolStripManager.Renderer プロパティ>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstripmanager.renderer.aspx]]

***ProfessionalColorTableクラス [#je98b55d]

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

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

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

#code(vbnet){{
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
}}

#code(csharp){{
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の外観を変更するには、次のようにします。

#code(vbnet){{
'アプリケーション全体にカスタムのプロフェッショナルレンダラを適用する
ToolStripManager.Renderer = _
    New ToolStripProfessionalRenderer( _
    New CustomProfessionalRenderer())
}}

#code(csharp){{
//アプリケーション全体にカスタムのプロフェッショナルレンダラを適用する
ToolStripManager.Renderer =
    new ToolStripProfessionalRenderer(
    new CustomProfessionalRenderer());
}}

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

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

私が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は全く無視され、どのようにすれば有効になるのか分かりませんでした。

[[ProfessionalColorTable クラス>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.professionalcolortable.aspx]]
-[[ProfessionalColorTable クラス>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.professionalcolortable.aspx]]
-[[ProfessionalColors メンバ>http://msdn2.microsoft.com/ja-JP/library/system.windows.forms.professionalcolors.aspx]]
-[[方法 : ToolStrip アプリケーションの色をカスタマイズする>http://msdn2.microsoft.com/ja-jp/library/ms229724.aspx]]
-[[方法 : 実行時に ToolStrip レンダラを設定する>http://msdn2.microsoft.com/ja-JP/library/ms229637.aspx]]

[[ProfessionalColors メンバ>http://msdn2.microsoft.com/ja-JP/library/system.windows.forms.professionalcolors.aspx]]

[[方法 : ToolStrip アプリケーションの色をカスタマイズする>http://msdn2.microsoft.com/ja-jp/library/ms229724.aspx]]

[[方法 : 実行時に ToolStrip レンダラを設定する>http://msdn2.microsoft.com/ja-JP/library/ms229637.aspx]]

***カスタムToolStripRenderer [#o912fe66]

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

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

[[ToolStripRenderer クラス>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstriprenderer.aspx]]
-[[ToolStripRenderer クラス>http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstriprenderer.aspx]]

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

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

#code(vbnet){{
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
}}

#code(csharp){{
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();
    }
}
}}

[[方法 : プロフェッショナル スタイルの ToolStrip コントロールを作成する>http://msdn2.microsoft.com/ja-JP/library/ms229725.aspx]]
-[[方法 : プロフェッショナル スタイルの ToolStrip コントロールを作成する>http://msdn2.microsoft.com/ja-JP/library/ms229725.aspx]]
-[[方法 : カスタムの ToolStripRenderer を実装する>http://msdn2.microsoft.com/ja-jp/library/ms229720.aspx]]

[[方法 : カスタムの ToolStripRenderer を実装する>http://msdn2.microsoft.com/ja-jp/library/ms229720.aspx]]

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

#code(vbnet){{
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
}}

#code(csharp){{
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の角を四角くする [#o2bd4e2a]

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

#code(vbnet){{
Dim proRenderer As New ToolStripProfessionalRenderer()
proRenderer.RoundedEdges = False
ToolStripManager.Renderer = proRenderer
}}

#code(csharp){{
ToolStripProfessionalRenderer proRenderer =
    new ToolStripProfessionalRenderer();
proRenderer.RoundedEdges = false;
ToolStripManager.Renderer = proRenderer;
}}

***ToolStripのVisualスタイルを無効にする [#t8d0bd40]

ToolStripManager.VisualStylesEnabledメソッドをFalseとすることにより、ToolStripのVisualスタイル(Windows XPで使用されている外観のスタイル)を無効にできます。つまり、VisualStylesEnabledメソッドをFalseとすると、ToolStripの見た目はWindows XPより古いWindowsで実行したExplore(レンダラがToolStripSystemRendererの時)やMS Office XP(レンダラがToolStripProfessionalRendererの時)のようになります。

今まで紹介してきたように、ProfessionalColorTableクラスや、ToolStripRendererの派生クラスを使ってToolStripの外観を変更した場合は、これらにより描画法が変更された箇所はVisualStylesEnabledメソッドの影響を受けないようです。逆に、VisualStylesEnabledの値によりカスタムToolStripRendererの描画法を変更したい場合は、ToolStripManager.VisualStylesEnabledの値を見て描画法を変更するようにします。

#code(vbnet){{
'Visualスタイルを無効にする
ToolStripManager.VisualStylesEnabled = False
}}

#code(csharp){{
//Visualスタイルを無効にする
ToolStripManager.VisualStylesEnabled = false;
}}

しつこいようですが、次回もToolStripに関するTipを紹介する予定です。

//これより下は編集しないでください
#pageinfo(,2010-03-19 (金) 02:06:32,DOBON!,2010-03-19 (金) 02:06:32,DOBON!)
#pageinfo(,2010-03-19 (金) 02:06:32,DOBON!,2010-03-19 (金) 02:17:11,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]