This article is about exploring the ability to create custom controls in the .NET platform, that make use of Windows XP's visual styles and themes. To that end, I have included a couple of fairly simple controls that mimic some of the behaviors that Windows Explorer implements in XP.
|
/////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2003 - Don Kackman
//
// Distribute and change freely, but please don't remove my name from the source
//
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// questions - contact me at dkackman_2000@yahoo.com
//
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Windows.Forms.Themes;
namespace System.Windows.Forms
{
/// <summary>
/// Abstract base Panel control to help out with rendering while themed and not themed
/// </summary>
public class ThemeablePanel : Panel
{
private ThemeInfo m_ThemeInfo;
private string m_WindowClassName;
/// <summary>
/// Initializes the ThemeablePanel class
/// </summary>
/// <param name="windowClassName">The window class name that will be used to retreive ThemeParts</param>
protected ThemeablePanel( string windowClassName )
{
m_WindowClassName = windowClassName;
m_ThemeInfo = new ThemeInfo();
BackColor = SystemColors.ControlLightLight;
SetStyle( ControlStyles.Selectable, false );
}
/// <summary>
/// This contructor is needed so derived classes can be used
/// by the designer. It shouldn't be called otherise
/// </summary>
protected ThemeablePanel() : this( "" )
{
}
/// <summary>
/// ThemeInfo instance for the control
/// </summary>
protected ThemeInfo ThemeInfo
{
get { return m_ThemeInfo; }
}
/// <summary>
/// Get the current window theme for the panel using the window class name
/// If the app is not themed returns null
/// </summary>
/// <returns>ThemeInfo object or null</returns>
protected WindowTheme GetCurrentWindowTheme()
{
WindowTheme theme = null;
// try and get the window theme
// If we can't catch the error and return null
try
{
// don't get a the window theme if the app isn't themed or we are in design mode
if ( UxTheme.IsAppThemed && !DesignMode )
theme = m_ThemeInfo[m_WindowClassName];
}
catch ( IndexOutOfRangeException )
{
}
return theme;
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
WindowTheme theme = GetCurrentWindowTheme();
if ( theme == null )
{
base.OnPaintBackground( pevent );
OnPaintUnthemedBackground(pevent);
}
else
{
OnPaintThemedBackground( pevent );
}
}
/// <summary>
/// Derived classes should override this method if they need to do custom
/// rendering on the background when the app isn't themed.
/// The base class implementation does nothing
/// </summary>
/// <param name="pevent">Paint event arguments</param>
protected virtual void OnPaintUnthemedBackground( PaintEventArgs pevent )
{
// base class implementation is a no-op
}
/// <summary>
/// Derived classes should override this method if the need to do
/// custom background rendering when the app is themed.
/// The base class implementation just does a nomral background paint
/// </summary>
/// <param name="pevent">Paint event arguments</param>
protected virtual void OnPaintThemedBackground( PaintEventArgs pevent )
{
//base class implementation just does a normal background paint
base.OnPaintBackground (pevent);
}
/// <summary>
/// Draw the specified theme part
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
/// <param name="bounds">Rectangle to pain into</param>
/// <param name="partName">The name of the part to paint</param>
/// <returns>The ThemePart object that is painted</returns>
protected ThemePart DrawPart( Graphics graphics, Rectangle bounds, string partName )
{
WindowTheme theme = GetCurrentWindowTheme();
ThemePart part = theme.Parts[partName];
part.DrawBackground( graphics, bounds );
return part;
}
/// <summary>
/// Draw the specified theme part
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
/// <param name="bounds">Rectangle to pain into</param>
/// <param name="partName">The name of the part to paint</param>
/// <param name="stateName">The name of the part's state to paint</param>
/// <returns>The ThemePartState object used to paint</returns>
protected ThemePartState DrawPart( Graphics graphics, Rectangle bounds, string partName, string stateName )
{
WindowTheme theme = GetCurrentWindowTheme();
ThemePart part = theme.Parts[partName];
ThemePartState state = part.States[stateName];
state.DrawBackground( graphics, bounds );
return state;
}
/// <summary>
/// Draws the specified part onto the control
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
/// <param name="control">The control who's bounds will be used to paint</param>
/// <param name="partName">The name of the part to paint</param>
/// <returns>The ThemePart object that is painted</returns>
protected ThemePart DrawPart( Graphics graphics, Control control, string partName )
{
return DrawPart( graphics, new Rectangle( 0, 0, control.Width, control.Height ), partName );
}
/// <summary>
/// Draws the specified part and state onto the control
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
/// <param name="control">The control who's bounds will be used to paint</param>
/// <param name="partName">The name of the part to paint</param>
/// <param name="stateName">The name of the part's state to paint</param>
/// <returns>The ThemePartState object used to paint</returns>
protected ThemePartState DrawPart( Graphics graphics, Control control, string partName, string stateName )
{
return DrawPart( graphics, new Rectangle( 0, 0, control.Width, control.Height ), partName, stateName );
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
The first computer program I ever wrote was in BASIC on a TRS-80 Model I and it looked something like:
10 PRINT "Don is cool"
20 GOTO 10
It only went downhill from there.
Hey look, I've got a blog