Partager via


Application.EnableVisualStyles

In Windows XP, the concept of Visual Styles was introduced to allow customization of the look and feel of windows and controls. Most applications that target Windows XP and above will want to take advantage of Visual Styles. In v1.1 of the .NET Framework, we added a way to programmatically enable visual styles in Windows Forms applications. Most .NET developers are most likely already familiar with the Application.EnableVisualStyles method. The purpose of this blog, therefore, is not to introduce this method, but to explain a little bit about what it actually does. I will also attempt to address frequently asked questions regarding this method. The rest of this post is in the form of an FAQ.

(Update: Most of the issues mentioned below are fixed in .NET Framework 2.0 (Whidbey). There are also a bunch of improvements in Visual Styles support in Windows Forms. See this post for a summary of the new features.)

Q What does Application.EnableVisualStyles actually do?

Windows XP ships with two versions of the Common Controls Library (comctl32.dll) - versions 5.8 and 6.0. v5.8 renders controls in the "Classic" style that you get on Windows NT/2000 and Windows 9x. v6.0 renders controls using the XP Visual Styles look and feel. Since most Windows Forms controls are based on comctl32, how they are rendered depends on which version of comctl32 is used to do the rendering. By default, v5.8 is used to render the client area of the app and v6.0 is used to render the non-client area. That is why you see the title bar and window borders automatically render "themed", while the controls (like Button, TextBox, ListView, ComboBox and so on) have the classic look by default.

In v1.0 of the Framework, the way to get visual styles in a Windows Forms app was to ship a manifest file with the app, that has information in it to indicate that v6.0 of comctl32 should be used for rendering. While this works fine, many developers felt it cumbersome to author, maintain and deploy manifest files. They felt the need to be able to do this programmatically. Now, the Platform SDK does provide API to do this. Basically, you need to create and activate an Activation Context that has pretty much the same DLL redirection information in it as the manifest file. The Activation Context API can be used to do this in a way suitable to your application.

If you take a look at these API, you will probably notice that they aren't very easy to use. While the advanced developers may like to tinker around with activation contexts, it is probably not something a developer who wants some "quick and dirty" code to get visual styles will do. So the Windows Forms team decided to wrap these API and expose a simple method that developers could call, that would isolate them from these complexities. So, essentially, when you call Application.EnableVisualStyles, we set up an activation context around the application's message loop, so that comctl32 function calls can be properly redirected to comctl32 v6.0. That way, you don't need to include a manifest with your app.

Q Why should Application.EnableVisualStyles be called before Application.Run?

As mentioned above, the activation context that we create is setup around the application's message loop. When EnableVisualStyles is called, we set a flag to indicate that a context needs to be activated. This flag is used to determine whether the activation context code is called or not during message loop setup. Application.Run sets up the message loop, so naturally the call to EnableVisualStyles should precede it.

Q Why should I set the FlatStyle property of some controls to System to get the themed look and feel?

For those controls that have FlatStyle properties, in all modes except FlatStyle.System, Windows Forms custom-renders the controls. In v1.0 and v1.1, the Windows Forms rendering code is not "theme-aware", so EnableVisualStyles has no effect unless comctl32 itself does the rendering. The FlatStyle.System setting does exactly that - tells Windows Forms to allow comctl32 to render the control. Unfortunately, in this mode, cool features like setting the BackColor or assigning an image to the control do not work, since to support these, Windows Forms needs to do the rendering.

Q I wish FlatStyle.Standard would give me the themed look. That way, I could get the best of both worlds - themed look and feel as well as features like assigning a BackColor or image.

Agreed! We are planning to make our custom rendering code more theme-aware in a future version of the Framework.

Q Some Windows Forms controls don't get themed properly - for example, the TabControl's body has a grey background, which looks rather inconsistent and the NumericUpDown control's up and down buttons aren't themed.

Yes, this is again due to the fact that Windows Forms custom rendering, unfortunately, isn't currently theme-aware. We will try and fix this in a future version!

Q I sometimes have weird problems with Application.EnableVisualStyles. Some controls don't seem to pick up theming; images that are assigned to TreeView nodes or ListView items sometimes don't render at all. However, when I use a manifest, I don't see these problems.

Yes, this is a known issue with the implementation of Application.EnableVisualStyles. The reason for this is as follows. As I mentioned before, the activation context is setup around the application's message loop. So any comctl32 handles created after the message loop is setup will be correctly redirected to v6.0. However, when you have the following code in Main:

Application.EnableVisualStyles();
Application.Run(new Form1());

Form1 is constructed before the message loop is setup. Therefore, any handle created in Form1's constructor code will result in that control being bound to v5.8 instead of v6.0, since the activation context has not yet been setup. This isn't as bad as it may sound, since in most cases, we delay handle creation as much as possible, so control handles aren't typically created in InitializeComponent. One rather common exception is the Imagelist - it turns out that in many cases, the Imagelist's handle is created in InitializeComponent, so you get a v5.8 imagelist that doesn't interop well with v6.0 controls on XP (on Windows Server 2003, the v5.8 imagelist does interop well with v6.0 controls, so you won't see this problem on that platform), the result being that the images don't show up. There are also some cases where some other control handles may get created early, in which case, those controls too will get bound to v5.8 and will not appear themed. We are obviously planning to fix this in the future, but for now, there are several workarounds that customers have used successfully. I list some of them here for reference:

  • Include a call to Application.DoEvents() before Application.Run().
  • Move the erring code (that causes handle creation to happen) from InitializeComponent to the Form's Load method.
  • Use a manifest!

Note that the above discussion applies only to the app's "Main Form", i.e., the Form that is passed to the Application.Run. Forms that are instantiated after the message loop is setup will be constructed after the context is activated, so code in their constructors shouldn't face this problem.

Q I am writing a Windows Forms control and I wish to make use of Visual Styles to ensure that my control's look and feel is consistent with the rest of the application. How can I do this?

Currently, there are no managed classes in the Framework to do this. You will need to p/invoke and use the UxTheme API. These API give you the ability to render common control parts, get information about visual style recommended colors, find out if a visual style is active and so on.

As always, feel free to let me know if you need any more information about Visual Styles or have any suggestions!

Comments

  • Anonymous
    October 08, 2003
    Thanks for the tip on Visual styles. the Application.DoEvents tip really helped me. Thanks again for the help.

  • Anonymous
    January 21, 2004
    It seems that the Windows.Forms.Textbox control does not get themed with Application.EnableVisualStyles

  • Anonymous
    January 24, 2004
    Thanks for the info on ListViews and ImageLists. It was very frustrating to think that I couldn't use the Visual Styles and Images in my ListView at the same time.

  • Anonymous
    January 24, 2004
    Taiwo: If you drop a textbox on a form and call Application.EnableVisualStyles before Application.Run, the textbox does pick up theming. In what situation are you seeing it not pick up theming?

  • Anonymous
    April 04, 2004
    Good Job!! Thanks for all

  • Anonymous
    April 06, 2004
    Sorry this comment isn't directly about .net and EnableVisualStyles, but its one of the few blogs that mentions themes, so perhaps you can fill in the blanks for me?

    Why property pages are sometimes rendered incorrectly with XP themes enabled? Are some of the following bits of XP using Forms?

    For Example in XP:
    Correct: http://www.gsection.com/general.png
    Wrong: http://www.gsection.com/summary.png

    Also with my unmanaged application, I find my own property pages dont render correctly if I perhaps just have an edit control on a property sheet, however if I place a static on there, then the the sheet renders in a themed way.

    Again sorry, if this is a way off comment.

  • Anonymous
    April 06, 2004
    Chris: I have forwarded your question to the guys that own the undeylying theme API and will post any information I get.

  • Anonymous
    April 06, 2004
    Excellent! Thanks very much.

  • Anonymous
    April 07, 2004
    Okay, here is the information I got back:

    "Without a button or static control on the property sheet, you need to explicitly call EnableThemeDialogTexture(hwndDlg, ETDT_ENABLE);

    Buttons (i.e. radio, check, groups) and Statics are inherently transparent, therefore placing one of these controls on the PropSheet makes this call for you implicitly."

    As for the summary page not being rendered correctly, that is apparently a bug they are aware of.

  • Anonymous
    May 29, 2004
    I'm a good friend of Chris Monachan's and I'd just like to say he is a top guy, and certainly knows his stuff about computers. If you've got any questions, he's the guy to ask.

  • Anonymous
    June 15, 2004
    While Application.EnableVisualStyles() works in one form, it doesn't seem to work for me when I create an instance of a new form and displays it (e.g. Form frm1 = new Form(); frm1.Show();). The interesting thing is, any button on the newly created form is correctly rendered using theme (when FlatStyle == System), but none of the other controls is rendered using theme.

    Any idea?

  • Anonymous
    June 15, 2004
    The comment has been removed

  • Anonymous
    June 23, 2004
    Good job !!

    This is the only place that actually explains the Application.EnableVisualStyles in a way that makes sense !

    Keep up the good work !!

    Tom

  • Anonymous
    June 29, 2004
    This is really cool which makes the look and feel of windows form with the XP windows system.

  • Anonymous
    August 03, 2004
    The comment has been removed

  • Anonymous
    August 04, 2004
    I think you have run into a known bug in the EnableVisualStyles implementation in .NET v1.1 (fixed in v2.0). My suggestion would be to use an application manifest to get visual styles instead. I have put in a request for a KB article on this issue.

  • Anonymous
    December 12, 2005
    I m using this method. But in my application it is effecting my docking style of form. I am using negavation bar. My application is exactly look like an Outlook Express. What i will do for docking?

  • Anonymous
    December 14, 2005
    Purav: How does this effect docking?

  • Anonymous
    March 01, 2006
    Any idea how to enable visual styles for controls on a explorer bar that gets add to the GAC ?

  • Anonymous
    March 01, 2006
    Hello - I receive the error mentioned before - without using this method. What could be the reason ?

  • Anonymous
    March 02, 2006
    Raj: You probably don't want to do that. It is best to respect the choice of the hosting application with respect to whether to enable visual styles or not.

    Florin: Not sure. If you can reproduce it, please report the problem through MSDN Product Feedback, and you should get a response pretty soon.

  • Anonymous
    April 24, 2006
    Is there a way to apply the XP style only to a particular control on the form and the rest of the controls will have to appear in a normal style?

  • Anonymous
    April 25, 2006
    Kiran: I think the underlying activation context API supports isolation, so can theoritically isolate a control to use commctrl v6, while all other controls use v5.

    In managed code, however, this is not supported and will be fraught with problems. This is because the CLR does not support the use of multiple activation contexts in a single app domain.

  • Anonymous
    May 04, 2006
    This is an excellent information than the msdn plain explanation of this functions.

  • Anonymous
    June 09, 2006
    i am using mdiparent app, .net 2.0, when Application.EnableVisualStyles run it cause my application to crash if I manually click the exe on my pc to run it. When I use VS2005 and run it in debug mode it runs fine..

    Application.EnableVisualStyles run in program.cs in the main method.

             Application.EnableVisualStyles();
                 
                   Application.SetCompatibleTextRenderingDefault(false);
                   Application.Run(new UI.Forms.MDIMainParent());


    In the MdiParent.designer.cs th eline that causes the crash is :
    this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image")));

    the complete error thrown is:

    CLR debugger

    An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll

    Source "mscorlib" string
    + StackTrace '$exception.StackTrace' threw an exception of type 'System.OutOfMemoryException' string {System.OutOfMemoryException}

    + TargetSite {System.Reflection.Assembly nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.Assembly, System.Threading.StackCrawlMark ByRef, Boolean, Boolean)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}


    - Non-Public members
    _COMPlusExceptionCode -532459699 int
    HResult -2147024882 int

    has anyone had this?

  • Anonymous
    June 12, 2006
    Hmm, this might be a bug. Please report it through MSDN Product Feedback and you should get a response soon. You could also try to post this on one of the forums.

    I have moved to a different team several months back, so I am afraid I don't have the context to help you out myself.

  • Anonymous
    July 18, 2006
    Hi, I have an Office AppAddin that at some point requires to display a progress bar, which only works if I have EnableVisualStyles.

    The assembly is not an exe, so is the only way for me to apply the visual styles by using the old method of supplying manifests for each MS Office App?  

    That is how I currently do it, and it works, but doesnt feel like the correct way to be doing it.

    Cheers
    Stephen

  • Anonymous
    July 21, 2006
    Stephen: Good question. Unfortunately, I have moved to a different team in Microsoft several months back, so I don't know what the current recommendation is for this scenario. Try posting this question on one of the forums or on MSDN Product Feedback and someone should be able to help you out.

  • Anonymous
    July 24, 2006
    Hi, I am fustrated with the problem I am having. I attempted to run a downloaded sample of a custom radio button cell in a DataGridView control. It compiles but then I get the following error message: System.InvalidOperationException was unhandled by user code
     Message="Visual Styles-related operation resulted in an error because no visual style is currently active."
     Source="System.Windows.Forms"
    Visual styles is enabled in the main routine. I included the DoEvent() call after enabling visual styles.  I have also tried including a manifest directing use of version 6 of comctl32.dll with no luck.  Any thoughts?
    I am using Windows XP Professional Build 2600.xpsp_sp2_grd.050301-1519
    Microsoft Visual C++ and C# 2005.

  • Anonymous
    August 01, 2006
    Dave: Sorry for the delay in replying to your question.

    Do you have visual styles actually enabled on your OS? If you are using Windows Classic theme in XP, for example, you would see this exception.

  • Anonymous
    September 05, 2006
    Prabhu,

    I did read your comments that you are not involved in this area anymore. But, I do have a quick question( sorry about that). Is the issue with the bitmaps and images not drawing resolved completely? Because, I still have an issue on XP SP2 with VS .NET 2005 generated Application( I would assume it's more dependent on the .NET framework version than the VS .NET version ).
    This is what I found:

    I have a WinForms app that has an ActiveX control (that's developed in C++ )in it. This ActiveX control has a Toolbar with buttons that have images on them. Now, when I load the ActiveX control the first time, no problem - the images on the button show up. However, when i reload the ActiveX, the images on the buttons disappear. I browsed through various
    posts and read about the .NET 1.1 issues with EnableVisaulStyles(). BTW, I am using EnableVisualStyles() in my app. It has no problems on a 2003 server with .NET framework 2.0 and VS .NET 2005. But, this weird behaviour only happens with XP SP2 and .NET 2.0/VS .NET 2005 on it.

    I tried calling the DoEvents() after the EnableVisualStyles(). No luck. However, if I comment out the EnableVisualStyles(), I have no problem.
    Then, I went the manifest route - voila, it solved the issue.

    So, my question is - is this still an issue? Did anyone report it so far?

    And, I am trying to see if this works on a 2000 Pro with .NET 1.1 installed and am frustrated since my WinForms App doesnt seem to be reading the manifest files on a 2000 machine. Is that true or am i doing something stupid??( I am a beginner of .NET. I am basically a C++ Developer )

    Any help is greatly appreciated.

    -Thanks,
    Rajesh

  • Anonymous
    September 05, 2006
    Rajesh:

    That does look like a variation of the same underlying problem. Basically, the problem occurs when you try to use a comctl v5 imagelist with comctl v6 controls. In .NET 2.0, we try to ensure that the Imagelist control always creates a comctl v6 imagelist if EnableVisualStyles() is called. However, we cannot control what a hosted native ActiveX control does. I suspect the control is creating a v5 imagelist in this case.

    The interop issue between comctl v5 and v6 (a Windows issue, not .NET) has been fixed in Server 2003, but not XP SP2, which explains why you don't see the bug on Server 2003.

    Anyway, using a manifest is probably your best option here.

    Regarding Windows 2000: Visual styles, and possibly even manifest based assembly loading, are not supported on OSes prior to XP. So neither does WinForms.

  • Anonymous
    September 06, 2006
    Thanks a lot for the explanation, Prabu.

    -Rajesh

  • Anonymous
    March 19, 2007
    Excellent information about Application.EnableVisualStyles here . We're used to shipping a manifest file

  • Anonymous
    June 04, 2008
    PingBack from http://justinhome.yourfreehosting.net/usexpvisualstylefile.html

  • Anonymous
    June 16, 2009
    PingBack from http://workfromhomecareer.info/story.php?id=18369

  • Anonymous
    June 16, 2009
    PingBack from http://fixmycrediteasily.info/story.php?id=959