RSS 2.0 Feed
RSS 2.0


Atom 1.0 Feed
Atom 1.0

  Enabling XP Themes in your .NET Applications 


qt8gt0bxhw|20009F4EEE83|RyanMain|subtext_Content|Text|0xfbffc40000000000b600000001000400

When you build Windows applications in .NET, by default your application will not have support for XP Themes, or Visual Styles. It is an easy enough task to do, and I think it goes a long way in giving your application a complete and professional look & feel. When Windows Forms 2.0 comes out with Visual Studio 2005 support for XP themes will be enabled by default in your Windows applications. However, for now you have two options for enabling XP theme support. These options are not new news or anything, but I did want to point out some problems with one of these methods (see option 1).

Before we get into these options, remember what enabling visual themes is really doing. Windows XP/2003 ships with two versions of the Common Controls library (comctl32.dll). Versions 5.8 and 6.0. Version 5.8 renders controls using the standard classic look that we've seen before, such as in Windows 2000 and 9x etc. Version 6.0 renders controls with the XP themed look and feel. So enabling visual styles in your application is nothing more than just creating an activation context around the application's message loop that redirects calls to comctl32 functions to version 6.0 of the comctl32.dll. Creating activation contexts is not that easy of a task and is definitely more work than it is worth to just get a themed look. When we get into these options we'll see that these give us some easier ways to provide this redirection to the version 6.0 of comctl32.


Option 1

With .NET 1.1 there was a new static method introduced in the Application class called EnableVisualStyles. This method enables visual themes in your application if the operating system supports it. Calling EnableVisualStyles causes all controls to be drawn with visual styles, so it must be called before any controls are drawn for the application. Typically, you will call EnableVisualStyles as the first thing in your main function - before your call to Application.Run.


[STAThread]
static void main() 
{
    Application.EnableVisualStyles();
    Application.Run(new Form1());
}


That is it. Easy enough. Basically, what EnableVisualStyles does is wrap the code to create the activation context and provide the redirection to the correct version of comctl32. However, this option does have it's problems. And some big ones too. Many .NET developers will likely already know about EnableVisualStyles, but I'll get questions all the time from developers that do not understand why it does not work at times and other problems in their application that are as a result of the call to EnableVisualStyles.  First of all, since what EnableVisualStyles is doing is setting up an activation context around the message loop, any comctl32 handles created after the message loop is set up will be redirected to comctl32 version 6.0. However, there are cases when the form will be created, which calls the constructor and the call to InitializeComponent, before the message loop gets created. You can get around this by adding a call to the static DoEvents (Application.DoEvents();) inbetween the call to EnableVisualStyles and Run. This will give the application the ability to completely setup the message loop before the form is created. When this problem happens, handles created in InitializeComponent will get created as version 5.8 comctl32 handles. You'll get some problems especially with ImageLists. Having a v5.8 ImageList does not interop well with v6.0 controls, such as ListViews and TreeViews. So this will cause the images to not show up. Other controls will not appear themed. At times I'll get critical exceptions halting execution of the application due to interop inconsistencies between the v5.8 handles and v6.0 controls. I tend to stay away from this option because of these problems, but in most cases a simple call to DoEvents will solve the issue. One thing to note here is that these problems are fixed in .NET 2.0 (which is a good thing since EnableVisualStyles is called by default for Windows applications.


Option 2

Instead of calling EnableVisualStyles, you can use a manifest file. This manifest file will cause the application to redirect comctl32 calls to the version 6.0 DLL when available. The issues discussed in option #1 do not happen with this option. This way does give you a safe, problem free way to enable visual styles, but it does create the need to distribute another file (and a use could delete that file which would make your application appear un-themed). You do not need to be the author of an app to create a manifest for it. It is a separate text file that you could create for any application, whether it is one that you built or not, to give it a themed look. A manifest file looks like this:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
<assemblyIdentity 
    version="1.0.0.0" 
    processorArchitecture="X86" 
    name="Executable Name" 
    type="win32" 
/> 
<description>Application description</description> 
<dependency> 
    <dependentAssembly> 
        <assemblyIdentity 
            type="win32" 
            name="Microsoft.Windows.Common-Controls" 
            version="6.0.0.0" 
            processorArchitecture="X86" 
            publicKeyToken="6595b64144ccf1df" 
            language="*" 
        /> 
    </dependentAssembly> 
</dependency> 
</assembly>


Note: Blog reader Charles pointed out in the comments that some of the characters were lost in the formatting as HTML leaving the XML malformed. I've fixed the post so all should be good now. Sorry for any headaches that might have caused. Thanks Charles.

You create a text file, add this text to it (modifying the Executable Name) and then name the file the same name as your exe (including the 'exe' extension part) with an extionsion of 'manifest'. For example, if your exe is named MyApp.exe, then you'd name the manifest file MyApp.exe.manifest and put it in the same directory as your exe. That is it. This will bind the application to the version 6.0 comctl32.dll. BTW, you can also add this manifest file into the application's resources. To do this you add it into the resources and give it a type of RT_MANIFEST with an ID of 1. Easy enough to do, but you'd have to add it back into the resources every time you recompile your app. I'm fine with just distributing the manifest file separately. No big deal to me.

Either option you choose to use, you also need to set any control with a FlatStyle property to 'System'. Using a FlatStyle of system will allow the FlatStyle to be determined by the operating system. You could use a loop to iterate through any controls that have a FlatStyle property, or just set it manually at design time. This is also something you won't have to do with Windows Forms 2.0 as it will happen automatically. But for now, you have to set this for any control that derives from System.Windows.Controls.ButtonBase.

Whether you personally like visual themes or not, the fact is that many of the users of your applications do. Since XP themes are on by default for new installs, chances are that most of your users on XP will have themes on. IMO not allowing your application to support themes gives the impression that there is something missing from your application. It is an easy enough task to do, so I say take the time to do it. As I stated earlier, all of this will be built into Windows Forms 2.0, but for now don't leave your applications looking stale.




                   



Leave a comment below.

Comments

  1. Ronan Molloy 7/1/2004 12:54 AM
    Gravatar
    Hi Ryan
    I followed your explanation to the letter, I even checked that there was 2 versions of the dll, but still my sample app of a radio button, button and checkbox are still not XP themed (I set the flatstyle to System).

    I used both options, enableVisualStyles with DoEvents() and the manifest file.

    I developing on windows server 2003. Are there any known issues ?

    thanks
    Ronan
  2. Ryan Farley 7/1/2004 7:25 AM
    Gravatar
    Hi Ronan,

    Windows 2003 does have the ability to use themes, but it is disabled by default. So even if you use the method described here, you will still not see any visual theme because the visual themes are not turned on. When you do what is described in this article, it basically makes your app match the theme that the OS is using (ie: it won't make it look themed if the OS is not using a theme). So even if a Windows XP machine is using the standard theme (ie: regular, non-luna look) then your app will appear that way also. All this is just a way to enable your app to use a theme, but it still will render based on how the OS looks.

    BTW, to turn themes on for Windows 2003, just go to your services and start up a service called "Themes". Then when you go into the Appearance tab of the Display properties you'll be able to choose from the luna themes also. With the themes turned on (and one selected) then your app will use the theme also using what was described in this article.

    Good luck.
    -Ryan
  3. Ronan Molloy 7/13/2004 7:53 AM
    Gravatar
    thanks Ryan for that - started the service, changed the appearance and can now view the app in xp style.

    /Ronan
  4. Ryan Farley 7/13/2004 9:23 AM
    Gravatar
    Glad to hear it worked for you Ronan.

    -Ryan
  5. Charles 7/14/2004 10:37 AM
    Gravatar
    Ryan

    I have just tried your sample manifest above, and have now got it working. A couple of things to note: the manifest is not well formed as you have shown it, causing an error when starting the application. Specifically, the first line should read

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    Also, all the closing tags are missing the /, so the final <assembly> should actually be </assembly>, for example.

    Otherwise, thanks. This is the first time I have found an example of a manifest that I could make work.

    Charles
  6. Ryan Farley 7/14/2004 10:58 AM
    Gravatar
    Doh! Looks like those characters got lost in the HTML formatting to colorize the code. Thanks a ton for pointing that out Charles! I've updated the post.

    Thanks again,
    Ryan
  7. canh 12/14/2004 11:45 PM
    Gravatar
    Dear Ryan,
    Can you help me that problem in window 98,2000.
    I had tried, but no success.
    thank you very much.
    canh
  8. Ryan Farley 12/15/2004 4:44 AM
    Gravatar
    canh,

    Are you referring to enabling themes in Win98/2000? Sorry, can't be done. Those OS'es don't support themes.

    -Ryan
  9. Johny 1/18/2005 2:28 AM
    Gravatar
    Dear Ryan,
    I enable visual themes using option 2, success.But i have tried my appl. on another winxp computer, it has given an error but,it works on another win 2000,9x etc. computer.

    I have SP2 but the other winxp comp does not....Is it a problem?
  10. Ryan Farley 1/18/2005 6:53 AM
    Gravatar
    Hi Johny,

    I can't say I've had that problem. I wonder if you would get the same error using the EnableVisualStyles method on that same machine?

    -Ryan
  11. Johny 1/18/2005 8:43 AM
    Gravatar
    Hi again Ryan,
    on my machine using EnableVisualStyle method effects only listboxs. Buttons and groupboxs are not effected by this methods,also like that on others...
    I have tried it both flatstyle.system and flatstyle.standart but always same problem...

    thanks.
  12. Ryan Farley 1/18/2005 9:03 AM
    Gravatar
    Johny,

    That is a strange one. I've never had that problem before, you do have themes enabled? As long as you have your FlatStyle set to system for any objects that derive from ButtonBase then you should be covered.

    I actually have a follow up post coming soon about a freeware control you can use to give a full themed look to the app. Maybe you'll get better results with that.

    -Ryan
  13. Gravatar
    Hi,
    I must make an application for my college.
    The college PC's OS is XP but it's theme is classic, I can't change it.
    I have .NET 1.0
    Can I make my application with XP style ?
    And how can I do that ?
    Thank you.
  14. Ryan Farley 2/1/2005 6:14 PM
    Gravatar
    In order for the application to show themed, the OS must have themes enabled. You cannot make your application use a luna XP theme if the OS is using something else. All you are really doing here is enabling your application to load the comctl32 version 6 which allows your application to inherit the look of the base OS.

    -Ryan
  15. Marcin 2/14/2005 12:26 AM
    Gravatar
    Hi all

    I had another problem with Visual Styles.
    Everything looks fine when I turn on visual styles using Application.EnableVisualStyle() but....
    When I set "Checked" attribute of my RadioButton to "TRUE" most controls loses their visual styles :(
    When I don't touch "Checked" attribute, everything is fine.

    Ha... event when I programatically modify this attribute after InitialiseComponents() method, visual styles dissapears :(

    I have found only one solution:
    Modify this attribute in Form_Load() method.

    I using XP Pro SP2 / Visual Studio .NET 2003

    Could sombody know the reason of that behavior ?
  16. Ryan Farley 2/15/2005 8:58 AM
    Gravatar
    Hi Marcin,

    I've not had that problem. I use radio buttons all the time and never had any problems loosing the style - or on any control for that matter. It would have to be something about when the controls are being created and timing with starting the message loop. Or maybe to do something with when you create the controls and the redirect to the v6 comctl32. Who knows.

    Are you creating the controls at runtime, or are these just controls dropped on the form in VS?

    -Ryan
  17. Marcin 2/21/2005 1:46 AM
    Gravatar
    Hi Ryan

    To do this stuff I have drop radio controls in VS.
    I thought, that my another code damages controls behavior.
    I have made new project (C#) and, put two radio buttons and call EnableVisualStyles().
    Everything it's ok... until I set "Checked" property of rabio button.
    Then styles dissapears.

    Strange :)

    Marcin
  18. Tadej 2/23/2005 1:07 PM
    Gravatar
    Hi Ryan.

    I am writing a MDI application, where I'd like to show the child window without the min/max/ctl buttons. To achieve this, I am using the following code snippet found in microsoft.public.dotnet.framework newsgroup:

    Form2 frm = new Form2();
    frm.MdiParent = this;
    frm.FormBorderStyle = FormBorderStyle.None;
    frm.ControlBox = false;
    frm.MinimizeBox = false;
    frm.MaximizeBox = false;
    frm.Show();
    frm.Dock = DockStyle.Fill;

    The problem is, that this solution works nice, as long as I do not use the EnableVisualStyles().

    When EnableVisualStyles() is used, rendering of the maximized child becomes unacceptably slow. One can actually see the child form being drawn for a fraction of a asecond and then it gets maximized.

    Any ideas why this behavior, how can it be workarounded or different way of diplaying the MDI child?

    Regards,
    Tadej
  19. vicky 3/31/2005 1:25 PM
    Gravatar
    Hi Ryan,
    Like Windows XP themes do we have any other such themes which can be applied to windows forms. If so please provide me the list and if possible their implementation to .net windows applications.
    Thanks,
    Vicky.
  20. Srikanth 4/6/2005 1:24 PM
    Gravatar
    Hi Ryan,

    I tried the manifest method. The buttons now wear the XP style, but the image cannot be seen. Any idea what should be done?

    Thanks!
    Srikanth
  21. Madni 5/4/2005 9:19 AM
    Gravatar
    I am using .NEt framework 1.0 so I cant able to add XP theme. I have .NET framework 1.1 installed but how can I change framework reference from 1.0 to 1.1 in Development Environment. right now the error is
    "E:\PROJECTS\Sofar Payroll\frmMain.vb(418): 'EnableVisualStyles' is not a member of 'System.Windows.Forms.Application'.
    "
    plz guide me to enable XP theme

    Kind Regards,
  22. Ryan Farley 5/4/2005 9:23 AM
    Gravatar
    Madni,

    To convert a 1.0 project to a 1.1 project you can just open the project in VS.NET 2003 and it will convert it for you. However, you don't need to convert it to just use visual styles. You don't need to call EnableVisualStyles for this to work. Just add a manifest file to your apps directory and that's it.

    -Ryan
  23. Phil Mellor 5/9/2005 6:17 AM
    Gravatar
    Just wanted to thank you for the above. The turning on of themes in Server 2004 was so obvious, and yet I over looked it for that last 4 months - I have been writting apps to be run over terminal services with the boring default theme!

    You are 'da man!
  24. Carlos Maroto 5/12/2005 2:33 PM
    Gravatar
    Hi Ryan,

    I was able to set my app to use XP styles but I have an issue with the .NET MonthCalendar control.

    When I select 1 day in the calendar, it looks fine with the blue selection color behind the date number (with font in white).

    The problem arises when I select more than 1 day, because the control displays the correct range of dates selected but most of the numbers can not be seen because a white bar appears across the range.

    I know the problem is the manifest, 'cause if I do not use it then the MonthCalendar works fine but, of course, my other controls will not be XP Style-like

    Any ideas about solving this issue?
    Thanks,
    Carlos
  25. Joorj 5/23/2005 4:50 AM
    Gravatar
    I need help to make application XP style and button forcolor = red how it doesnot work I used Winxp sp1

    please help me
  26. Subhendu 7/3/2005 10:34 PM
    Gravatar
    ryan
    I have a problem i have developed a project on Windows XP which is a asp.net web application using VB. now when i am accessing the Web pages from 2000 it looks dull could any thing be done for that to make it look like the same as i prepared.

    subhendu
  27. Mike Hofer 7/6/2005 6:23 AM
    Gravatar
    Hey! This worked beautifully for my .NET 1.1 application.

    My application uses a treeview with bitmaps on each node, and listviews with bitmaps on each item as well. When I enabled visual styles, the controls no longer render my bitmaps.

    Any idea what I should do?
  28. Ryan Farley 7/6/2005 10:56 AM
    Gravatar
    Hi Mike,

    I actually have been planning a new post on this subject for quite some
    time. What I like to use for this now is a free component that handles the
    themeing much better. You'll find that it can properly theme controls that
    have images, like buttons, treeviews, listviews, etc and not loose the
    images. It also can theme tabs and panels better than the standard methods
    (EnableVisualStyles or using a manifest).

    The control is free and you can get it here:
    http://www.skybound.ca/developer/visualstyles/default.aspx

    Good luck.
  29. Mike Hofer 7/8/2005 5:29 AM
    Gravatar
    That control worked exceptionally well! Thanks very much!
  30. Ryan Farley 7/18/2005 2:34 PM
    Gravatar
    subhendu,

    It does look the same as you prepared it. When you view the webpage on XP it will appear themed to match your OS, when you view it on 2000 it does not have theming, but the markup is the same, it is the OS that displays it differently. View the page on a mac and it will look different according to how that OS renders the page.

    -Ryan
  31. Deepak 8/23/2005 6:34 AM
    Gravatar
    Hi Ryan,
    I tried using second method.
    My application is a smartclient, XP effects areworking fine on my machine but when I tried launching the application at some other machine, no effect turned up. The other machine also have Comctl32.dll that is required for the effect.
    Could you pls provide any help
  32. Ryan Farley 8/23/2005 7:29 AM
    Gravatar
    Deepak,

    Are the other machines XP as well? If they are not then you won't have any luck, all you are doing is just allowing your app to look like the theme that is enabled on the host machine, but I'm sure you know that.

    Anyway, since your app is a SmartClient, is it being delivered on run via a URL? If so then option 2 won't help you because it won't get delivered with the app. Why not just use EnableVisualStyles? With option 2, yo can embed the manifest as a resource in the binary itself, but any time you recompile you have to do it all over again.

    To embed the manifest into the exe as a resource, look at the following article and look for the section titled "Add the Manifest to the Executable File".

    http://msdn.com/library/en-us/dv_vstechart/html/vbtchUsingWindowsXPVisualStylesWithControlsOnWindowsForms.asp

    -Ryan
  33. David 9/11/2005 10:17 PM
    Gravatar
    Hi Rayn,

    I tried both of your options. 1st is working with listview problems. But 2nd is not working. I am using windows xp 1sp. please help!
  34. David 9/11/2005 10:40 PM
    Gravatar
    By the Way, my application has a MDI form. Is that cause the problem?
  35. Adam 10/2/2005 9:10 PM
    Gravatar
    I figured the bug had to have a work around. I have NO idea if this is doing anything besides giving the message loop thread a head start, but it works consistently in my case. First, the class:

    //////////////////////////////////////////////////////////////////////////
    /// Created By: Adam Root ///
    /// Created On: October 2, 2005 ///
    //////////////////////////////////////////////////////////////////////////

    using System;
    using System.Reflection;

    namespace Win32
    {
    public sealed class VisualStylesHelper
    {
    private VisualStylesHelper()
    {
    }

    public class EnableVisualStylesInScope : IDisposable
    {
    /// <summary>
    /// The underlying theme enabling object. While this object exists,
    /// we (supposedly) have themes enabled.
    /// </summary>
    private object styles;

    /// <summary>
    /// Creates a default instance. While the instance exists and has not been
    /// disposed, themes are enabled.
    /// </summary>
    public EnableVisualStylesInScope()
    {
    // Get the System.Windows.Forms assembly
    Assembly swf = Assembly.GetAssembly(typeof(System.Windows.Forms.Control));
    // Look through the types to find the SafeNativeMethods type
    foreach (Type type in swf.GetTypes())
    {
    if (type.Name == "SafeNativeMethods")
    {
    // Locate the EnableThemingInScope type. This is the key to enabling themes, as it
    // contains the Win32 calls to do it
    Type EnableThemingInScopeType = type.GetNestedType("EnableThemingInScope", BindingFlags.NonPublic);
    // Get a handle on the constructor
    ConstructorInfo constructor = EnableThemingInScopeType.GetConstructor(new Type[] { typeof(bool) });
    // Locate the EnsureActivateContextCreated method
    MethodInfo EnsureActivateContextCreatedMethod = EnableThemingInScopeType.GetMethod("EnsureActivateContextCreated", BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Any, new Type[0], null);
    // Create an instance
    styles = constructor.Invoke(new object[] { true });
    // Loop until the activate context is created
    while (!(bool)EnsureActivateContextCreatedMethod.Invoke(styles, new object[0]))
    {
    System.Diagnostics.Debug.WriteLine("LOOP");
    }

    // Done
    break;
    }
    }
    }

    ~EnableVisualStylesInScope()
    {
    Dispose(false);
    }

    #region IDisposable Members

    public void Dispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
    // Remove our reference to the underlying theme enabler
    styles = null;
    }

    #endregion
    }
    }
    }

    To use this, I have this Main() method:

    static void Main()
    {
    #if true
    using (VisualStylesHelper.EnableVisualStylesInScope styles = new VisualStylesHelper.EnableVisualStylesInScope())
    {
    Application.Run(new Form1());
    }
    #else
    Application.EnableVisualStyles();
    Application.DoEvents();
    Application.Run(new Form1());
    #endif
    }

    Note that if I change the #ifdef true to #ifdef false, my application causes a NullReferenceException *every* time. Let me know if this does or doesn't work for you!

    Adam
    adam@staractive.com

  36. Joe Mayo 10/8/2005 2:43 PM
    Gravatar
    Hello,

    I'm wanting to have xp style in a windows user control when embedded in internet explorer. The dll's don't use the *.manifest file.

    Any ideas?

    JoeM
    joem@hecktech.com
  37. Al 11/20/2005 12:43 AM
    Gravatar
    Hi Ryan,
    Enabling visual styles worked fine, thanks. But the following problem arised: transparent background does not work for styled checkboxes (with FlatStyle=System). I have several checkboxes on a groupbox which has background image. Non-styled checkboxes with transparent background looks OK, but styled fills it background with white color.

    Do you have any ideas?

    Thanks, Al
  38. Al 11/20/2005 12:53 AM
    Gravatar
    PS: using skybound components also not helps :(
  39. Gravatar

    Does this work with DLL as a stand along project ?

    Avtar Khaba

  40. louk 6/20/2006 4:30 AM
    Gravatar
    Hi Ryan,

    a ListView which contains an ImageList where large Icons has been assigned to, does under .net 2.0 (VS 2005) show the Icons if Application.EnableVisualStyles() ist NOT called in Main (old style). If Visual Styles are enabled, the Icons DONT appear. Do you have an idea, what the reason could be and how to fix it.

    With .net 1.1 (VS2003) it worked fine that way in addition to calling DoEvents().

    Regards,

    louk
  41. louk 7/11/2006 3:22 AM
    Gravatar
    See <a href="http://www.codeproject.com/cs/miscctrl/MgXpImageButton.asp?forumid=33600&exp=0&select=1566071&df=100#xx1566071xx" rel="nofollow">Code is obsolete for .NET 2.0...</a> for an answer.

    Regards,

    louk
  42. alan 7/26/2006 5:35 AM
    Gravatar
    Did I miss something here?
    I included manifest as explained but I get a missing file message:
    "This application as failed to start because MFC80.dll was not found".

    I found the file here:
    C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_dec6ddd2

    And I'm not even sure what this directory is.

    Can anyone explain what's going on here?

    thanks



  43. teamels 8/10/2006 5:46 PM
    Gravatar
    Nice tip on the Manifest file for V1.x Framework

    Thanks
  44. Amol 9/24/2007 1:46 AM
    Gravatar
    Hi Ryan,
    I am using .NET 2.0. I have a form which uses list view control. I am using imagelist to display a sort indicator on the column header. When I run the project as exe it works fine. But when I use the same form from a COM dll the image from the imagelist does not show up.

    I tried both the optios but nothing worked.

    Can you help please?

    Thanks in advnace ..
  45. pavan 3/2/2009 7:28 AM
    Gravatar
    Hi,

    i tryed applying the same to user control, when i try to integrate it into web application as an activex control these styles are not beeing applied. can you help on this
Comments have been closed on this topic.



 

News


Also see my CRM Developer blog

Connect:   @ryanfarley@mastodon.social

         

Sponsor

Sections