I think you need to see the themes in the WPF application. An assembly may contain the following lines:
[assembly:. ThemeInfo (ResourceDictionaryLocation SourceAssembly , ResourceDictionaryLocation.SourceAssembly)]
This means that the system themes of the application are located in your assembly (in the folder / themes). The theme name should correspond to system topics ... for example:
The Aero theme (Windows Vista and Windows 7): themes\Aero.NormalColor.xaml The default Windows XP theme: themes\Luna.NormalColor.xaml The olive green Windows XP theme: themes\Luna.Homestead.xaml The Windows Classic theme: themes\Classic.xaml
When the user changes the skin of the system, the WPF application automatically downloads your themes. Accordingly, you can set a control template for each system theme. More information can be found in:
"Adam Nathan. WPF 4 Unleashed." Chapter 14.
WPF Themed Applications: http://blogs.infosupport.com/theming-wpf-applications/
Hope this helps.
* EDIT *
I found an interesting example that talks about the topic of topic change:
http://northhorizon.net/2010/how-to-actually-change-the-system-theme-in-wpf/
You can set an explicit style that will not respond to skin changes in the system:
<Style x:Key="ExplicitGreenButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"> <Setter Property="Background" Value="Green" /> <Setter Property="Foreground" Value="White" /> </Style>
Accordingly, an implicit style will respond to a change in the system skin:
<Style x:Key="ImplicitGreenButtonStyle" TargetType="Button"> <Setter Property="Background" Value="Green" /> <Setter Property="Foreground" Value="White" /> </Style>
In addition, the example contains useful code in ThemeHelper , in which some topics work.
* EDIT # 2 *
If I understand correctly, first you need to get the name of the system theme. This action can be performed in several ways.
First, use the Win32 functions from the UxTheme.dll library, for example GetCurrentThemeName () :
[DllImport("uxtheme.dll", CharSet = CharSet.Auto)] public static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars, StringBuilder pszSizeBuff, int cchMaxSizeChars); StringBuilder stringThemeName = new StringBuilder(260); StringBuilder stringColorName = new StringBuilder(260); StringBuilder stringSizeName = new StringBuilder(260); Int32 s = GetCurrentThemeName(stringThemeName, 260, stringColorName, 260, stringSizeName, 260);
But I got this function incorrectly received some names of system themes, such as "Classic". So I tried differently.
The second way is to get the topic name from the registry. In the path, "HKEY_CURRENT_USER \ Software \ Microsoft \ Windows \ CurrentVersion \ Themes \ LastTheme" contains the current system theme. So we need to intercept the "Change system theme event" with a window hook.
Below is an example with several buttons, the style of which depends on the system theme:
Add to window:
SourceInitialized="Window_SourceInitialized"
Styles
<Style x:Key="DefaultStyle" BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}"> <Setter Property="Background" Value="CadetBlue" /> </Style> <Style x:Key="LunaStyle" TargetType="{x:Type Button}"> <Setter Property="Background" Value="Blue" /> <Setter Property="Foreground" Value="White" /> </Style> <Style x:Key="ClassicStyle" TargetType="{x:Type Button}"> <Setter Property="Background" Value="Gray" /> <Setter Property="Foreground" Value="Black" /> </Style>
Main grid:
<Grid> <Button Style="{StaticResource DefaultStyle}" Content="Default button" Width="100" Height="30" VerticalAlignment="Top" HorizontalAlignment="Left" /> <Button Name="ChangeButtonStyle" Content="Changes style" Width="100" Height="30" VerticalAlignment="Top" HorizontalAlignment="Right" /> <TextBlock Name="CurrentTheme" FontSize="16" Text="Null" Width="150" Height="30" HorizontalAlignment="Center" VerticalAlignment="Top" /> </Grid>
In code:
Intercept the "Change system theme" event:
private IntPtr hwnd; private HwndSource hsource; private void Window_SourceInitialized(object sender, EventArgs e) { if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero) { throw new InvalidOperationException("Could not get window handle."); } hsource = HwndSource.FromHwnd(hwnd); hsource.AddHook(WndProc); } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case 0x31A:
Get the name of the system theme and set the style:
public string SubKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\LastTheme"; public string Value = "ThemeFile"; private void GetThemeName(string OpenKey, string Value) { RegistryKey pRegKey = Registry.CurrentUser; pRegKey = pRegKey.OpenSubKey(OpenKey); Object val = pRegKey.GetValue(Value); string NameThemeFile = val as string; if (NameThemeFile.IndexOf("Luna") != -1) { ChangeButtonStyle.Style = this.FindResource("LunaStyle") as Style; CurrentTheme.Text = "Luna"; } if (NameThemeFile.IndexOf("Classic") != -1) { ChangeButtonStyle.Style = this.FindResource("ClassicStyle") as Style; CurrentTheme.Text = "Classic"; } }
This method is not the best, but it will begin.