Themed Controls






Themed Controls

All common Windows controlsTextBox, CheckBox, RadioButton, and so onsupport Windows themes. A Windows theme specifies how the basic elements of the desktop UI are rendered. Modern versions of Windows, such as Windows XP, support controls that are rendered to a particular Windows theme, such as "Windows Classic" or "Windows XP." The theme they render to is specified via the Display Properties dialog, shown in Figure.

3. Changing the Windows Theme


One of the main aspects of a theme is that a user can adjust the way the basic controls are drawn at any time and expect the entire desktop and all applications to automatically update themselves to support the new theme. For example, when buttons aren't themed, they look like those in Figure.

4. Unthemed Buttons in Windows XP


However, when the Windows XP theme is applied in the Display Properties control panel, buttons (and other standard controls) render themselves to match, as shown in Figure.

5. Themed Buttons in Windows XP


To let you render the standard Windows controls in Windows themes, Windows Forms uses the EnableVisualStyles method (implemented by the System.Windows.Forms.Application class). When you create a new Windows Forms application, themed rendering is enabled by default in a generated application entry point:[2]

[2] If you use the VS05 Windows Application project template to create your project, the main entry point for the application is created in Program.cs.

// Program.cs
[STAThread]
static void Main() {
  Application.EnableVisualStyles();
  ...
}

The call to EnableVisualStyles ensures that your controls render to the current Windows theme when loaded, and, after they're running, they automatically update themselves to reflect further theme changes.

Tool Strip Render Modes

By default, the MenuStrip, ToolStrip, and StatusStrip controls all support theme-sensitive rendering, in that they have the same look as the Office 2003 tool strips across the various themes. However, tool strips offer additional rendering modes that allow you to override the current theme using special renderer classes.

The type of renderer class used at any given time by a tool strip is determined by the RenderMode property, which is exposed by all tool strips. RenderMode can be one of the four ToolStripRenderMode enumeration values:

namespace System.Windows.Forms {
  enum ToolStripRenderMode {
    [Browsable(false)]
    Custom = 0, // Can't set this RenderMode property in
                // the Properties window
    System = 1 // Windows apps appearance (default for StatusStrip)
    Professional = 2, // Office 2003 appearance
    ManagerRenderMode = 3,  // Renderer determined by ToolStripManager
                          // (default for MenuStrip and ToolStrip)
  }
}

Windows Forms comes with two stock tool strip renderers: ToolStripSystemRenderer and ToolStripProfessionalRenderer.[3] The former is used when RenderMode is set to System, and the latter is used when RenderMode is set to Professional. To see the difference, look at Figure.

[3] Windows Forms also comes with two specialized renderers for high-contrast and low-resolution scenarios: ToolStripHighContrastRenderer and ToolStripProfessionalLowResolutionRenderer. However, these are marked as internal and are unavailable for your use.

6. Tool Strip System and Professional Render Modes


The System render mode gives the look and feel you'd expect to find on a variety of applications that come with Windows, including Calculator (calc.exe) and WordPad (wordpad.exe). Professional, on the other hand, renders in the same way as Office 2003 applications.

By default, both MenuStrip and ToolStrip actually have their RenderMode properties set to ManagerRenderMode, and this means that they yield the choice of renderer to ToolStripManager. The renderer used by ToolStripManager is set via its Renderer property, which defaults to ToolStripProfessionalRenderer. When ToolStripManager.Renderer is set to a tool strip renderer, ToolStripManager applies it to all tool strips on a form whose RenderMode is set to ManagerRenderMode. This gives you a shortcut for swapping renderers and applying them in one fell swoop, rather than individually for each tool strip.

On the other hand, StatusStrip's RenderMode property is set to System by default. This causes StatusStrip to render as gray, with the rounded shading style that you find in VS05 rather than the flatter style in Office 2003. You can make the StatusStrip render flat, too, when its RenderMode is Professional, but, as you can see in Figure, it's colored blue with a highlight on the top edge. If you want it flat but colored gray with a highlight, you have a fourth RenderMode option: Custom. However, setting the RenderMode property to Custom actually causes an exception, and that is why the RenderMode.Custom enumeration value is hidden from the Properties window using the Browsable attribute.[4] RenderMode is set to Custom implicitly as a result of using a custom tool strip renderer.

[4] BrowsableAttribute is one of many attributes that influence how types operate in the Windows Forms Designer's design-time environment. These attributes are discussed in Chapter 11: Design-Time Integration: The Properties Window.

Custom Tool Strip Rendering

If you need custom tool strip rendering, you create a custom tool strip renderer class to paint the StatusStrip (or any tool strip) the way you want. A custom tool strip renderer derives from the abstract ToolStripRenderer base class, which offers a host of protected virtual methods you can override to paint the various elements of a tool strip:

namespace System.Windows.Forms {
  abstract class ToolStripRenderer {
    ...
    protected virtual void OnRenderArrow(...);
    protected virtual void OnRenderButtonBackground(...);
    protected virtual void OnRenderDropDownButtonBackground(...);
    protected virtual void OnRenderGrip(...);
    protected virtual void OnRenderImageMargin(...);
    protected virtual void OnRenderItemBackground(...);
    protected virtual void OnRenderItemCheck(...);
    protected virtual void OnRenderItemImage(...);
    protected virtual void OnRenderItemText(...);
    protected virtual void OnRenderLabelBackground(...);
    protected virtual void OnRenderMenuItemBackground(...);
    protected virtual void OnRenderOverflowButtonBackground(...);
    protected virtual void OnRenderRaftingContainerBackground(...);
    protected virtual void OnRenderSeparator(...);
    protected virtual void OnRenderSplitButtonBackground(...);
    protected virtual void OnRenderStatusStripSizingGrip(...);
    protected virtual void OnRenderToolStripBackground(...);
    protected virtual void OnRenderToolStripBorder(...);
    protected virtual void OnRenderToolStripContentPanelBackground(...);
    protected virtual void OnRenderToolStripPanelBackground(...);
    protected virtual void OnRenderToolStripStatusLabelBackground(...);
    ...
  }
}

Each of these methods is passed an argument that provides a Graphics object that wraps the underlying tool strip's drawing surface. It also provides several additional properties specific to the piece of the UI being rendered. To create a custom tool strip renderer that paints a tool strip's background gray with a highlight, you derive from ToolStripRenderer and override its OnRenderToolStripBackground:

class CustomStatusStripRenderer : ToolStripRenderer {
  protected override void OnRenderToolStripBackground(
    ToolStripRenderEventArgs e) {

    Rectangle backgroundRect = e.AffectedBounds;
    Graphics g = e.Graphics;

    // Fill rectangle
    g.FillRectangle(SystemBrushes.Control, backgroundRect);

    // Draw highlight
    using( Pen highlightPen =
      new Pen(SystemColors.ControlLightLight) ) {
      g.DrawLine(highlightPen, 0, 0, backgroundRect.Width, 0);
    }
  }
}

The area to which you need to paint the background is defined as a Rectangle that you retrieve from the AffectedBounds property of the ToolStripRenderEventArgs argument. Then it's painting as usual, à la Chapter 5: Drawing Basics and Chapter 7: Advanced Drawing. To use your custom tool strip renderer, you set your tool strip's Renderer property to point to an instance of it:

void customRadioButton_CheckedChanged(object sender, EventArgs e) {
  this.statusStrip1.Renderer = new CustomStatusStripRenderer();
}

The result is shown in Figure.

7. StatusBar with Custom Renderer (see the white line along the top of the StatusBar)


When you set the Renderer property of a tool strip to a custom renderer, the tool strip automatically changes its RenderMode to Custom. So, even though you can't set the RenderMode property yourself, you can at least detect whether a tool strip is using a custom renderer.

ToolStripSystemRenderer and ToolStripProfessionalRenderer also derive from ToolStripRenderer, and that's how they get their unique tool strip rendering services. Consequently, you may need to write less code in your custom tool strip renderers if you derive from either, especially when they provide the basic appearance you require. Either way, there are many more ways to alter the appearance of both a tool strip and its items, although that discussion is beyond the scope of this book.[5]

[5] You will find a great introduction sample and discussion of custom tool strip rendering at http://www.windowsforms.com/Samples/Go%20To%20Market/Tool%20Strips/ToolStrip%20GTM.doc#Toc116357041 (http://tinysells.com/19).

Custom tool strip rendering lets you take over the painting of tool strip controls. This ability is also available for a variety of common Windows Forms controls using a technique known as owner-draw.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows