#title(.NETプログラミング研究 第67号) #navi(.NETプログラミング研究) #contents *.NETプログラミング研究 第67号 [#a75560e4] **.NET Tips [#cc475534] 今回も前回に引き続き、ToolStripとToolStripContainerに関するTipsを紹介します。 **ToolStripやToolStripContainerの外観を変更する [#ac8585b8] #column(注意){{ この記事の最新版は「[[ToolStripやToolStripContainerの外観を変更する>http://dobon.net/vb/dotnet/control/tsrenderer.html]]」で公開しています。 この記事の最新版は「[[ToolStripやToolStripContainerの外観を変更する>https://dobon.net/vb/dotnet/control/tsrenderer.html]]」で公開しています。 }} 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]] ***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]] ***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]] -[[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]] もし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]] -[[方法 : カスタムの 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を紹介する予定です。 **コメント [#i7e6122b] #comment //これより下は編集しないでください #pageinfo([[:Category/.NET]],2006-03-23 (木) 06:00:00,DOBON!,2010-03-23 (火) 02:26:13,DOBON!) |