Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Fully customizable Menu-, Tool-, ContextMenu-, and Status strips

4.81/5 (19 votes)
3 Mar 2010CPOL4 min read 1   3.3K  
Change the colors used to render Menu-, Tool,- ContextMenu-, and Status strip controls during design-time.

imgRed.jpg

Introduction

As you may or may not know, the MenuStrip, ToolStrip, ContextMenuStrip, and StatusStrip controls (hereafter called 'Strips' or 'Strip controls', for short) can be customized to a great extent. They use the ToolStrip(Professional)Renderer class to render themselves, and it is possible to inherit this class and override the painting behavior. Of course, it takes a little effort to do that, as you are basically writing the drawing code manually.

If all you want is to change the colors of any of the Strip controls, but keep the shapes of everything (rectangular buttons, etc.), then there is a quicker way. The constructor of the ToolStripProfessionalRenderer accepts a ProfessionalColorTable, which is like a theme for the Strip controls. When supplied with a ProfessionalColorTable, the ToolStripProfessionalRenderer paints itself using the colors as specified in the ProfessionalColorTable.

While that is a much quicker way to customize your Strip controls, it still forces you to write code (inherit the ProfessionalColorTable class and override all color properties, returning your own values). These controls were designed to let you customize the colors of any of the Strip controls very easily, in the Visual Studio designer, without having to write a single line of code.

Furthermore, you change the colors in a component that can be re-used by as many Strip controls as you like. So, if you need a MenuStrip and a ToolStrip to look the same, you don't need to change their colors separately. You change the colors of this component, and they will use the same colors.

Also, your custom color definitions can be saved and loaded to and from XML files, so you can even distribute them to friends or coworkers.

Finally, there are 6 presets available that you simply have to choose from the list. The colors will then be set to mimic the colors for:

  • Office 2007 (blue)
  • Office 2003 Blue (default Windows XP style with Blue theme)
  • Office 2003 Silver (default Windows XP style with Silver theme)
  • Office 2003 Olive (default Windows XP style with Olive theme)
  • Office XP (default Windows Vista / Windows 7 style)
  • Office Classic (default style for Classic theme)

imgPresets.jpg

As you can see, the three default styles in Windows XP are also present, so you can even use the Silver theme in a Windows XP environment with a Blue theme.

Background

I made this as a project for myself. I thought it was odd that the .NET Framework provides the ability to customize the Strip controls, but doesn't provide it to the average user (e.g.: in the form of properties). I started out with a simple MenuStrip control that provided the colors via properties, but as there are so many, the properties list became very long and unwieldy. It was also a problem that you had to set the colors a second time (on the ToolStrip) when you wanted it to look the same. Or, even more times if you need more Strip controls. In short: it was still impractical.

With these controls, you only need to set the colors once, using properties in simple categories, and you can apply that theme to any Strip control you like.

Using the code

You don't need to write a single line of code to use these controls. All that is required are the following actions:

  • Build the project containing the files.
  • Drag an AppearanceControl (found in the toolbox after building) to your form.
  • Drag one or more Strip controls (found in the toolbox after building) to your form.
  • Set the Appearance property of the Strip controls to the AppearanceControl component on your form (use the dropdown in the property grid).
  • Explore the properties of the AppearanceControl. Use the Preset property to set a preset theme, or use the CustomAppearance property to change the colors manually.
  • In the Appearance Editor window that pops up, find the color property you need and change it. View the result instantly in the preview Strips.

imgEditor.jpg

Note: for the Strips to use the colors as defined in CustomAppearance, the Preset property must be set to Custom.

Points of interest

How does it work?

The AppearanceControl component uses an instance of a class that inherits ProfessionalColorTable internally. Instead of returning hardcoded values, it returns the colors as set in the CustomAppearance property:

VB
Public Class CustomColorTable _
             Inherits ProfessionalColorTable

    Private ac As AppearanceControl = Nothing

    Public Sub New(ByVal appearanceControl As AppearanceControl)
        ac = appearanceControl
    End Sub

    Overrides ReadOnly Property ButtonSelectedHighlight() As Color
        Get
            Return ac.CustomAppearance.ButtonAppearance.SelectedAppearance.Highlight
        End Get
    End Property

    Overrides ReadOnly Property ButtonSelectedHighlightBorder() As Color
        Get
            Return ac.CustomAppearance.ButtonAppearance.SelectedAppearance.BorderHighlight
        End Get
    End Property

    '...
End Class

In addition to this CustomColorTable class, there is a ColorTable for every preset which does use hardcoded color values.

The AppearanceControl exposes a ToolStripProfessionalRenderer, which has its ColorTable set to one of the internal color table classes.

Finally, the Strip controls (CustomizableMenuStrip, CustomizableToolStrip, CustomizableContextMenuStrip, and CustomizableStatusStrip) listen for a change in their AppearanceControl. When the Appearance property is set, they change their renderer from the default renderer to the Renderer property exposed by the AppearanceControl.

VB
Protected Overridable Sub OnAppearanceControlChanged(ByVal e As EventArgs)
    If Me.Appearance IsNot Nothing Then
        AddHandler Me.Appearance.AppearanceChanged, _
                   AddressOf AppearanceControl_AppearanceChanged
        AddHandler Me.Appearance.Disposed, _
                   AddressOf AppearanceControl_Disposed
        Me.Renderer = Me.Appearance.Renderer
    Else
        Me.Renderer = New ToolStripProfessionalRenderer()
    End If
    Me.Invalidate()

    RaiseEvent AppearanceControlChanged(Me, e)
End Sub

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)