Introduction
Support for XP Themes is known to be somewhat haphazard - the Explorer bypasses the theme DLL, UxTheme, for example. Microsoft refuses to open themes to developers for fear rampant new themes will cause "application incompatibilities."
I choose not to mess with UxTheme and the like, but I would like my applications to be aware when themes are in use. Because there are only four, at least right now, it is feasible to write code that reacts to the user's choice of theme. The user can choose "Windows Classic" or "Windows XP." If they choose the latter, they can select Blue (the default), Olive Green, or Silver color schemes.
[Added]
Thanks to Konrad Windszus and Rene Koenig, who point out that peeking in the registry is brittle and likely to break in future versions. That's an important disclaimer, along with this: Do not modify the registry hoping to change the theme.
I revised the code to illustrate Konrad's suggestion of calling UxTheme's IsThemeActive()
method and Rene's IsAppThemed()
. I still can't find an easy way to get UxTheme to tell me whether the user has chosen Blue, Green, or Silver.
Use the Registry
The answer is found in the registry, but it's not obvious. To save you experimenting, I'll just tell you:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager
ThemeActive is "1" if Windows XP, "0" if Windows Classic.
If ThemeActive is "1", ColorName will be "NormalColor" for blue, "HomeStead" for olive green, or "Metallic" for silver. (All of these data values are type REG_SZ, or strings, by the way.)
The following C# code illustrates reading the settings. Other languages are quite similar.
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
class Class1 {
static void Main()
{
Console.WriteLine("CurrentTheme returns {0}", CurrentTheme());
Console.WriteLine("UxTheme::IsThemeActive returns {0}", IsThemeActive());
Console.WriteLine("UxTheme::IsAppThemed returns {0}", IsAppThemed());
Console.Read();
}
public enum Theme
{
WindowsClassic,
XPBlue,
XPGreen,
XPSilver
}
public static Theme CurrentTheme()
{
RegistryKey key =
Registry.CurrentUser.OpenSubKey(
@"Software\Microsoft\Windows\CurrentVersion\ThemeManager");
if (key != null)
{
if ("1" == (string) key.GetValue("ThemeActive"))
{
string s = (string) key.GetValue("ColorName");
if (s != null)
{
if (String.Compare(s, "NormalColor", true) == 0)
return Theme.XPBlue;
if (String.Compare(s, "HomeStead", true) == 0)
return Theme.XPGreen;
if (String.Compare(s, "Metallic", true) == 0)
return Theme.XPSilver;
}
}
}
return Theme.WindowsClassic;
}
[DllImport("UxTheme")]
static extern bool IsThemeActive();
[DllImport("UxTheme")]
static extern bool IsAppThemed();
}
References
This article was inspired by an anonymous CodeProject article on XP-style buttons: http://www.codeproject.com/cs/miscctrl/JPEnhancedXPButton.asp, based on the work of someone named Joaqs. The anonymous article adds a "BtnStyle" property for the programmer to specify Blue, Silver, or Olive, but offers no hints how to detect the current state.
History
- 03/21/04 ad Revised
- 03/19/04 ad Initial