WPF comes with a few theme assemblies, one for each Windows theme (Luna, Royale and Aero and the fallback theme, Classic.) Usually the theme is loaded according to your current system theme, but if you want to create a consistent look for your application, you may want to force-load a specific one.

To accomplish that, simply add the following code in your Application Startup event (this example shows how to use the Aero theme):

Uri uri = new Uri(“PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\\themes/aero.normalcolor.xaml”, UriKind.Relative);

Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);

It’s important to specify the version and the public key token. Otherwise you’ll have to copy the theme assembly to the folder of your executable. The reason I’m adding it to the merged dictionaries collection is that I don’t want to lose other resources I added to the App.xaml file.

I usually put this code in a try…catch block (with an empty catch) since it doesn’t really impair the application’s functionality if it fails to execute.

Last note: From my experience, Windows Server 2003 always shows the Classic theme in WPF (even if you activate the Windows Themes service), so if you’re deploying applications for that platform, you may want to use this trick (you will also want to turn on your display adapter’s hardware acceleration and the DirectX accelerations, as they are disabled by default in 2003.)

Edit: Robby Ingebretsen (notstatic.com) also blogged about this because the new Zune theme, which caused WPF to fallback to the Classic theme. However, he placed the code in XAML. Here is a version of that using merged dictionaries (which will allow you to add other resources to App.xaml):

<Application.Resources>
    <
ResourceDictionary>
        <
ResourceDictionary.MergedDictionaries>
            <
ResourceDictionary Source=/PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\themes/aero.normalcolor.xaml />
        </
ResourceDictionary.MergedDictionaries>

        <!– other resources go here –>

    </ResourceDictionary>
</
Application.Resources>

Update: The Orcas designer seems to be having problems with the relative URI. Using an absolute URI solves the issue: (I’ve also attached a sample Orcas project)

pack://application:,,,/PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\themes/aero.normalcolor.xaml

Attachment: ForcedTheme.rar

Tagged with:
 

28 Responses to Forcing WPF to use a specific Windows theme

  1. Ranz says:

    I ‘m new in WPF and I try to find the the useful of App.xml file. So it is use to declare a style/template for a Window. Am I right?

  2. aelij says:

    App.xaml contains an application definition, which means it generates a Main() method (note this file has a different Build Action.) You can set all sorts of application-wide configuration settings in it, consume events such as Application.Startup, etc. It also contains the Application-wide Resource Dictionary, where you can put resources (not just templates and styles; a resource can be anything) available everywhere. So, it’s the best place to put a theme that all controls use.

  3. Brannon says:

    Thanks for the post. Two questions:

    1. Where did 31bf3856ad364e35 come from and what would it be for the other themes like Luna?

    2. Is it possible to apply this to an ElementHost (or its Child)? It seems to not work for me using the above code but modifying the Resources to be the member from the Child of ElementHost.

  4. aelij says:

    Hi Brannon,

    1. This is the assembly’s public key token. You can see it in the GAC (\Windows\Assembly folder.) All of WPF assemblies are signed with the same key, so the token is the same for PresentationFramework.Luna as well.

    2. You’ll need a few things to get this working:

       – Specify the theme dictionary at the top element (the Child in ElementHost) like I showed. Alternatively, if you don’t want to repeat this for every control in XAML, you can do it in code after instantiating it in the winform’s code-behind (using the Child’s Resources property.)

       – You do not have to use merged dictionaries. I recommend that you specify all resources in a level below the root. It should matter to your app, since resource lookup is always from child to ancestor.

       – If you specify a default style for an element, be sure to use BasedOn, like in the example below.

    <

    UserControl xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“>
    <
    UserControl.Resources>
        <
    ResourceDictionary Source=”/PresentationFramework.Luna;V3.0.0.0;31bf3856ad364e35;component\themes/luna.normalcolor.xaml” />
    </
    UserControl.Resources>
        <
    Grid>
            <
    Grid.Resources>
                <
    Style TargetType=”ButtonBasedOn=”{StaticResource {x:Type Button}}“>
                    <
    Setter Property=”MarginValue=”10,5,10,0” />
                    <
    Setter Property=”WidthValue=”60“/>
                </
    Style>
                <
    Style x:Key=”inlineTextTargetType=”TextBlock“>
                    <
    Setter Property=”MarginValue=”10,5,10,0” />
                </Style>
            </
    Grid.Resources>
            <!–
    rest of the code –>
        </
    Grid>
    </
    UserControl>

  5. Vinod sa says:

    How to create a custom themes for aour application and then use it?

  6. aelij says:

    You can create a theme assembly, in which there would be resource dictionaries that override the default styles. You should put the dictionaries under the "Themes" folder. After that you can load the theme from the assembly the same way I described above. You can create as many assemblies as you like and switch between the themes in runtime by changing the Application.Current.Resources property.

  7. TeamWork says:

    Can someone upload an example, please? I have tried several options, but I haven’t been able to make the Aero Theme work on Orcas.

  8. aelij says:

    I’ve attached a sample project for Orcas.

  9. Yiling says:

    Hi aelij,

    I want to use window classic theme. So I add reference to PresentationFramework.Classic.dll. The code like below:

    Uri uri = new Uri("PresentationFramework.Classic;V3.0.0.0;31bf3856ad364e35;component\\themes/classic.normalcolor.xaml", UriKind.Relative);

    this.Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);  

    But it will throw exception:

    Cannot locate resource ‘themes/classic.normalcolor.xaml’.

  10. aelij says:

    There is no “normal color” for the classic style. Just use “classic.xaml”. Normal color refers to the theme hue; for example, XP (aka “luna”) has three (normalcolor – blue, homestead – green and silver).

    You can view the theme names in Reflector (they appear in the assembly resources). Also, they are documented, albeit in an obscure enough place(http://msdn2.microsoft.com/en-us/library/system.windows.themeinfoattribute.themeinfoattribute.aspx).

    PS – why would you want to use that theme? It’s oh so ’95 :P

  11. Yiling says:

    Hi aelij,

    Thanks for your timely reply.

    Althought it’s very old, but it is really classic. :)

  12. Manish says:

    When I put the Resource Dictionary Tag inside PageFunction tag it is throwing error. Can anybody please help me make this work.

     <ResourceDictionary Source="/PresentationFramework.Luna;V3.0.0.0;31bf3856ad364e35;component\themes/luna.normalcolor.xaml" />

  13. aelij says:

    Manish,

    This is because PageFunction is a generic type. You can specify the Resources property using the base type, like so:

    <PageFunction …>

       <FrameworkElement.Resources>

           <ResourceDictionary … />

       </FrameworkElement.Resources>

    </PageFunction>

  14. Chris says:

    After installing .NET 3.0 together with the Windows Vista SDK on my Windows XP, I was happy to see that I could even get a Windows application to use Aero Style controls within Windows XP. Wow.

    However, is it possible to let the window itself appear in a Vista fashioned style? You know… black color, Vista style close/maximize buttons, etc… ?

  15. aelij says:

    Hi Chris,

    There's no easy way of getting the Vista window chrome, since it is controlled by the operating system, not WPF.

    You can, however, be creative and create it using WPF elements, and use an API (such as the Blendables ChromelessWindow or by directly calling Win32 API) to hide the original chrome and show your own.

    Components imitating the Office 2007 Ribbon (such as DevComponents' WPF Ribbon) also change the chrome to match Office, so check them out.

    Aelij.

  16. Jorge says:

    Many thanks. This tip is a life saver.

  17. Robert says:

    Hi there.

    Is it possible to ‘steal’ the window background fill when my Vista is running with the Vista Basic theme enabled? (NOT the Aero glass, but Vista Basic background)

  18. aelij says:

    I’m not sure what you mean by ‘window background'; is it the window title bar background?

    If so, there is no direct way to do this in WPF. Instead you can use the VisualStyleRenderer (which wraps uxtheme.dll) do draw into a GDI+ Bitmap object, and then convert to to a WPF BitmapSource using the System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap() method.

  19. Robert says:

    Thank you very much for your reply.

    Yes, it’s exactly what I want. I’ll try to use that method to see what I can get.

  20. Robert says:

    I’ve tried to do as you told me, but I get a stupid "Parameter is invalid" exception when trying to create a new Bitmap(). Here is the code

    try

    {

    System.Windows.Forms.VisualStyles.VisualStyleRenderer renderer = null;

    System.Windows.Forms.VisualStyles.VisualStyleElement element = System.Windows.Forms.VisualStyles.VisualStyleElement.Window.FrameRight.Active;

    if (System.Windows.Forms.VisualStyles.VisualStyleRenderer.IsElementDefined(element))

    {

    renderer = new System.Windows.Forms.VisualStyles.VisualStyleRenderer(element);

    System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap((int)this.RenderSize.Width, (int)this.RenderSize.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(gdiBmp);

    g.Clear(System.Drawing.Color.Red);

    renderer.DrawBackground(g, new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), new System.Drawing.Size((int)this.RenderSize.Width, (int)this.RenderSize.Height)));

    g.Dispose();

    System.Windows.Media.Imaging.BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(gdiBmp.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

    System.Windows.Media.ImageBrush imgBr = new ImageBrush(bs);

    return imgBr;

    }

    else

    return null;

    }

    catch (Exception ex){ return null; }

    Do you know what the problem might be?

    Thank you.

  21. Robert says:

    Figured it out in the meantime. Thank you very much, again and sorry for posting too much code text previously.

  22. aelij says:

    It's okay. I guess the problem was with RenderSize being (0,0). It is updated only after the layout is done, so you should call your code from the OnRender() override or use another way (such as the DesiredSize property) to get the size.

     (BTW, you should also call Dispose() on gdiBmp after you've converted it to BitmapSource. Or better yet, put both the Graphics and the Bitmap objects in a using block [which translates to try…finally] thus ensuring Dispose is always called.)

  23. Robert says:

    Yep, I’ve already Dispose() – ed my gdiBmp. Good point. And the problem was indeed coming from RenderSize being (0,0).

    Thanks a lot for your tip – I’ve been looking for how to do this (the Vista Basic bk ‘stealing’) for a few weeks but nobody gave me a good answer like yours :)

  24. Gufran says:

    its not working in windows server 2003 sp1 with 3.5 framework

  25. Absolutely beautiful… good post :)

  26. TrackBack says:

    One of the most popular posts in this blog is the one explaining how to override the system theme and

  27. Libing says:

    hi, i works for forcing to using aero theme, but i encounter a problem if i forced to use aero them in window server system, the controls is not readable in high contrast mode. do you know the reason and help me to solve that ?

Set your Twitter account name in your settings to use the TwitterBar Section.