Introduction

When Windows XP was first released with Windows XP Visual Styles, or "theming", many people were excited about the new look. When .NET was nearing the 1.0 release, however, many of the same people - including myself - were disappointed that Windows Forms did not support Windows XP Visual Styles. After doing some research into the Visual Styles API and the Microsoft .NET Framework SDK documents, I realized that Visual Styles are not hard to add to a .NET application.

The tutorial that follows is a simple process for adding visual styles to your applications and controls. After setting up your project, this tutorial will cover the basic types of controls that can use Windows XP Visual Styles, what makes the visual styles work, and how to tell Windows to theme your applications and controls.

Prerequisites

Microsoft Windows XP, the only currently, fully-released Windows operating system that supports theming and is needed for testing (optional)

Getting Started

Getting started is simple (though none of this is hard): open Visual Studio .NET and create a new Windows Application. I'll be using C# for this tutorial, so if you're using Visual Basic .NET, you'll need to translate the code. Once your project is created, open the AssemblyInfo.cs file and fill-in the AssemblyTitle, AssemblyDescription, AssemblyVersion (get rid of dynamic versioning for simplicity with this tutorial), and change AssemblyDelaySign to true. You'll also want to change AssemblyKeyFile to @"..\..\KeyFile.snk", which is a string literal pointing at a file we'll create (or copy) later.

When you're finished, your code should look something like the following:

Now, open Form1.cs and add many controls to it, such as ListViews, Buttons, GroupBoxes, ProgressBars, and more. The full list of controls that support visual styles are:

TextBox

RichTextBox

HScrollBar

VScrollBar

ProgressBar

TabControl

MainMenu

ContextMenu

ComboBox

DataGrid

ListBox

ListView

TreeView

DateTimePicker

MonthCalendar

Splitter

TrackBar

StatusBar

ToolBar

TreeView

ListView

Of these controls, several support theming by default. Others - specifically the ones that derive from ButtonBase, GroupBox, or Label - require that you set the FlatStyle property to System, which I'll explain shortly.

Once you've compiled your application, you'll noticed that the visual style of Windows Forms does not look like the Windows XP Visual Style. To figure out why, read on.

How Windows XP Visual Styles Work

Simply put: Comctl32.dll, version 6. Comctl32.dll, or the Common Controls, have been around for a very long time. This library provided basic common controls while User32.dll provided user controls. In version 6 of the Common Controls, all of the controls were put in Comctl32.dll so that all the controls could support theming. Comctl32.dll, version 6, is not redistributable, however, unlike previous versions of Comctl32.dll. In order to use the new Windows XP Visual Styles, you must be using an operating system that contains Comctl32.dll, such as Windows XP.

For supported controls, the control style is associated with a particular theme resource that is drawn in the client area of the control. For controls deriving from ButtonBase, GroupBox, and Label, these controls must use the FlatStyle.System enumeration member in their FlatStyle property so that they allow the operating system to draw the controls.

In order to tell Windows to use theming for your controls, you need to tell Windows to bind to Comctl32.dll, version 6. By default, Windows binds to Comctl32.dll, version 5. Similar to the binding policies of .NET, however, we can tell executables at runtime to bind to other assemblies, or Win32 libraries in this case.

So, add a new XML file to your project and call it [YourApp].exe.manifest, where [YourApp] is the name of the output file your project generates, which is your project name by default. Set the Compile Type to "None", since we'll only including this in your project for simplicity.

If you used the AssemblyInfo.cs code above, your newly created [YourApp].exe.manifest should look like:

You should replace the first "version" and "name" attributes with appropriate values for your project, which are the AssemblyVersion and AssemblyTitle attributes respectively. The "description" element should also match your AssemblyDescription attribute.

Next, open a command prompt and change directories to your project output directory, which should be "bin\Debug" with your project directory as the root. Assuming that you have sn.exe in your PATH (part of the .NET Framework SDK), type the following:

sn.exe -k ..\..\KeyFile.snk

This should put a public key file named KeyFile.snk - which we referred to earlier in our AssemblyInfo.cs file - in your project directory. This public key is necessary to sign your assembly with a strong name, which is required in many situations and is recommend for every assembly.

Adding the Manifest and the Final Touches

You should now be in the same directory as your project output file. In my example, my application is simply WindowsApplication1.exe, which I'll refer to later.

Now, back in Visual Studio .NET, click on the File->Open... menu, browse to your application such as WindowsAppication1.exe, and click open. You should now see your resources in a tree view.

Right-click on the root node WindowsApplication.exe and select "Add Resource...".

Save all files and go back to your resource view you were previously in. You should now see a folder named RT_MANIFEST.

Click on the newly added RT_MANIFEST resource, probably named 101. Change its ID to 1 in the property grid and save your application again.

After closing the resource view in which your application was open, go back to the command prompt and type the following:

sn -R WindowsApplication1.exe ..\..\KeyFile.snk

The tool should print some version info and then display:

Assembly 'WindowsApplication1.exe' successfully re-signed

Run your application and see Windows XP Visual Styles at work in your .NET application!

Summary

Windows XP Visual Styles can be a very good addition to your applications and control libraries and they don't take a lot of work. Supporting this new visual style will give your application a common look-and-feel with Windows, which is always a definite plus in commercial applications. Many companies strive to keep up with Windows standards and now you can do it without a lot of work.

Just remember to set the FlatStyle property of any applicable control to FlatStyle.System and to embed the manifest resource like the boilerplate above in your executable after compiling. After having done all that, you need only finish signing your assembly, otherwise it won't pass validation if you specified an AssemblyKeyFile. If you need to test your application or have an authority sign it, you can turn off validation for that assembly by typing the following:

sn.exe -Vr WindowsApplication1.exe

Go on now, start cranking out those Windows XP-like applications and controls and make your products stand out above the rest. It doesn't take a lot of work but your results are stylish and beneficial.

Share

About the Author

Heath Stewart is a happily married software engineer originally from the Midwest and a graduate of Iowa State University. Heath start programming early in life and enjoys continuous research and development in new languages, frameworks, and platforms. Fluent in many different programming languages, he has developed many large-scale software solutions for companies in different areas, such as Internet filtering, intrusion detection systems, production management systems, and web applications for various purposes. He also enjoys photography.

Currently, Heath is a Program Manager in the Visual Studio Professional Deployment Experience (VSPro DEX) team at Microsoft. Previous to his employment, he was a Microsoft MVP for Visual C#.

He is also a CodeProject protector and is happy to help the development community.

Comments and Discussions

I read the thread "How to enable XP styles for DLL" but I did not find a solution for my problem. First the facts about my DLL:

- My DLL is a stacically linked MFC DLL
- The DLL will run partially in the Shells Explorer process (I placed a control on the Taskbars RebarWindow32)
- I start my DLL with RunDL32.EXE DLLNAME, Start
- My development environment VC++6

I added a manifest as ressource to my DLL, with ID 1, 2, 123 ... and it will not work.

The strange thing is when I start the DLL from the VC6 IDE I'll have my DLLs window displayed in XP style, as I expect. But when I start my
DLL from the command line (rundll32.exe ...) I will not have the DLLs window displayed in XP style.

The only think what work is to place a manifest "right behind" rundll32.exe (rundll32.exe.manifest). But this is not a good solution, this will force all DLLs called by rundll32 to display in XP style....

Please read the messages below before posting the same thing for the "umpteenth" time. Application.EnableVisualStyles is only defined in .NET 1.1 and above. If you look at the article date, you might notice that .NET 1.1 wasn't even released yet.

What you have - besides being unable to compile, but I understand it's only a snippet of code - could lead to threading issues. You need to give the Common Controls time to load correctly otherwise you may not see the visual styles applied correctly and could also get load errors.

This posting is provided "AS IS" with no warranties, and confers no rights.

Thanks for the knowledge in the article! No matter that I found it when it was obsolete, it still taught me a lot of things... So, thank you for that!

You were right about DoEvents(): the buttons, for instance didn't get the style, and I was kindda wondering about that!.. Why doesn't MSDN update that?However.. I must disagree with you in another matter.. About switching from 1.0 to 1.1.. If that is hard, how about moving to 2.0? I thing this is a must for any company if it wants to stay in the top of the game.. I do not know about the costs, but I think they are minimal compared with the benefits! Anyway.. I'm not an owner, but I am a new technology addict ! So after seeing the beta from 2005, it comes very hard to open 2003! (I guess that makes me not very objective about the subject, though)

Staying "on top of the game" is not about who has or uses the coolest technology, but about providing a solution to a real problem and making that solution the best. The reason for the .com crash years ago was that everyone had a solution but few actually solved a problem.

The company I previously worked for - having architected a rather large N-tier application - was built on 1.0. Moving to 1.1 costs money. There was consideration about moving to 2.0, but only because of its underlying features that we previously implemented ourselves now becoming standard.

Yes, the toolbar, menu, and status strips are cool and generics are great - but only if you need them.

Finally, this article isn't necessarily obsolete. The .NET Framework is hefty - especially if you're installing on an IA64 or X64 (AMD64 or EM64T). ISVs can't always force such a large runtime down people's throughs and expect them to be willing to, say, install it across a network. That was the problem we had at our previous company (though I suspect it's better these days, now that this ".NET thing" has been taken more seriously lately). If your application must work with whatever is on a system, then you pretty much have to target 1.0. Costs to update aren't all on the ISV to upgrade their toolset and, if necessary, their code base; but also on the clients that must upgrade their machines and maintain both the runtime and vendor's application across their network (if applicable).

This posting is provided "AS IS" with no warranties, and confers no rights.

You are obviously right! There no question that you must respect your clients previous investments and yours for that matter! I only wanted to underline the fact that in an ever flooded market, it's not the coolest technologies that must be considered, but the most efficient, in both developing time and value (and I think I’m not wrong assuming that 1.1 is more efficient and “powerful” than 1.0). Am I wrong saying that a company should consider investing in that? That really is all I want to say. It is obvious that if an application already runs on 1.0, as long as that list on the http://www.gotdotnet.com/team/changeinfo/Backwards1.0to1.1/default.aspx is big and will stay that way, what is began must continue.
As a result, you are right about the obsolete statement.. I was wrong! Again, let me tell you that I had lots to learn and this is what was all about when writing this article, right?

Let me introduce you to the Common Language Infrastructure (CLI), the basis for the .NET Framework (which consists of the CLR, the CTS, and the BCL, among other things). Whatever language you write your code in compiles to about the same thing in Intermediate Language, or IL (technically, MSIL which includes a few extensions to the standard).

So, it doesn't matter whether you wrote your code in VB.NET or in C# because it compiles to almost exactly the same thing (C# has a few optimizations that have nothing to do with whether a Win32 manifest applies or not).

The manifest file - when written correcly, would work for any application written in any application so long as the compiled product uses the APIs (and the CLR - not any specific language - does) that can load side-by-side Win32 assemblies (like the Common Controls 6 library required for Visual Styles).

Try this: compile your app in either language but don't embed the manifest. Just call it "yourapp.exe.manifest" and stick it in the same directory.

If you're trying to use the C# code about in a VB.NET project, it wouldn't compile. But the BCL is the same for any language that uses it (although some basic languages like JScript.NET can't access non-CLS-compliant members like unsigned types). The language really has nothing to do with it.

If you need additional help, please be more specific. What's your manifest look like? And don't forget to encode the < and > with &lt; and &gt; so it actually shows up. Did you be sure to change the FlatStyle on all the controls?

This posting is provided "AS IS" with no warranties, and confers no rights.

You follow the same directions for setting the FlatStyle, but you can't simply enable visual styles for your UserControl. The application that contains your control must have enabled visual styles through a manifest (or bind against Common Controls 6 - which you're not supposed to do).

It all comes down to which version of the Common Controls library gets loaded into the process.

A control library can, however, request that visual styles are not applied to it, but that has to do with telling Common Controls not to draw themes for the controls defined by a particular library.

This posting is provided "AS IS" with no warranties, and confers no rights.

My UserControl(developed using C#) has a VScrollBar.
I am interested in applying XP Visual style to the VScrollBar Only. Other controls present in my UserControl , for them normal Style [look and feel] are OK and as par the approved design.

Heath wrote:
A control library can, however, request that visual styles are not applied to it, but that has to do with telling Common Controls not to draw themes for the controls defined by a particular library.

Jay's Commnet:
I see some rays of light here. Can you please ellaborate the point.
Can I enable visual styles to the vScrollBar? How?

I am really sorry for disturbing you with several questions. Still I believe that your guidence will do some trick.

As I have said already, you must have visual styles enabled for an application in order to apply visual styles for a control that the application contains. I don't see how you're seeing any "rays of light" here. I've stated this several times.

The keyword in my statement you quoted was that controls can tell Windows to not apply visual styles if an application uses a manifest to load the SxS common controls 6 library.

Adding the manifest to the EXE works fine! Is there any possibility to add the manifest during design time (with the visual studio) or with a kind of script. It's very arduous to add the manifest every time you rebuild your application!

You need to write an add-in to do this. Any files you add to your project in Visual Studio currently and set as an "Embedded Resource" get added to the assembly as an embedded resource, not a Win32 resource.

hello
i have downloaded your source code and tested in my computer(windows xp),it works well,but when i put a "RichTextBox" control in your form,it seem like that the RichTextBox couldn't change its appearance to xp visual style,according to the msdn articles,the RichTextBox DO have its own windows xp visual style,but why it don't works in your code example?