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.
Update: a bug where a TabPage
or a GroupBox
within a TabPage
is not drawn with theme data has been fixed in .NET Framework 2.0 beta. Please read http://blogs.msdn.com/heaths/archive/2005/04/19/409699.aspx for more information.
Prerequisites
You will need a few things to complete this tutorial:
- The Microsoft .NET Framework SDK (required)
- Microsoft Visual Studio .NET, which really aids in designing your Windows Forms (optional)
- 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:
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Theme Test")]
[assembly: AssemblyDescription("Testing Windows XP Visual Styles.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile(@"..\..\KeyFile.snk")]
[assembly: AssemblyKeyName("")]
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:
="1.0" ="UTF-8" ="yes"
<assembly
xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Theme Test"
type="win32" />
<description>Testing Windows XP Visual Styles.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*" />
</dependentAssembly>
</dependency>
</assembly>
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...".
- Click "Import...", browse for WindowsApplication.exe.manifest in your project directory, and click "Open".
- In the "Resource Type" text box, type
RT_MANIFEST
and click "OK".
- 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.