Theme Manager: A Hackly Hack
One of the most popular posts in this blog is the one explaining how to override the system theme and get the Vista look on non-Vista systems. This is possible because WPF ships with the theme files for all operation systems (well, all Microsoft OSs that WPF works on, i.e. XP, XP Media Center and Vista) and due to the fact that WPF doesn’t really use the system resources to get the OS theme, but rather relies on a private implementation of them that resides in the PresentationFramework.{Classic, Luna, Royale, Aero} assemblies.
The solution offered in the aforementioned post loads a selected theme dictionary from one of these assemblies to the Application resource dictionary. While this is enough to modify the theme for all the built-in controls, you may encounter problems in the following scenarios:
- You’re using third-party controls that have their own themes for each of the system themes. Many of these controls have a method of bypassing the system theme. (For example, see the Theme property on the Xceed DataGrid.)
- You’re writing a theme for your own control. Resources in the Themes folder do not go through the same lookup chain as other resources, so when you’re using built-in controls there, their theme may not be affected by the Application resource dictionary.
As an experiment , I’ve decided to hack into the bowels of WPF and force it to recognize a different theme as the system theme. I must say this is one of the ugliest hacks I’ve ever done. The result is the class ThemeManager, which exposes a single static method:
public static void ChangeTheme(string themeName, string themeColor);
Examples of theme name and color pairs: { “luna”, “homestead” }, { “royale”, “normalcolor” }, { “classic”, “” }. If you pass two empty strings, the default system theme will return. You can also invent a new theme of your own, give it a name and load it this way. I haven’t tried it, but it should work, as long as you conform to the theme dictionary location conventions.
I also hooked into the message loop and am intercepting the theme change message that is sent to all windows. This blocks WPF from attempting to apply a new theme when the system theme changes.
Needless to say I’m using tons of reflection and it’s likely to break in the next version, so don’t use it. I think this should have been part of the API to begin with.
PS – A helpful tip for the theme author: you can find the sources (XAML) for all the themes in the Windows SDK samples (look in WPFSamples.zip/Core/{Classic, Luna, Royale, Aero}Theme.)
Update: Apparently this still works in .NET 4 (as of Beta 2).
Attachment: ThemeMangerDemo.zip
Tags
.NET 4 Animation AppFabric Async Axum Blog C# ClearType Cloud CLR CodeValue Contests Deep Zoom Experiments Generics Google Ink Lectures Modeling Performance Personal Pivot Prism Programming Languages Prolog Reflector RTL Sela Silverlight The Arbel Network Themes Threading Tips Visual Studio WCF Windows 7 Windows 2003 Windows Azure Windows Forms Windows Phone Windows Vista Windows XP WPF XAML ZuneArchives
- May 2013
- February 2013
- June 2012
- May 2012
- June 2011
- November 2010
- August 2010
- July 2010
- June 2010
- March 2010
- December 2009
- November 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- November 2007
- September 2007
- June 2007
- May 2007
- February 2007
- November 2006
- October 2006
- February 2006
- August 2005
- February 2005
- August 2004
- July 2004
- June 2004
- May 2004





