Have a question? ask www.kenlet.com
Home  |  FAQ  |  About  |  Contact  |  View Source   
 
SEARCH:
 
BROWSE:
    My Hood
Edit My Info
View Events
Read Tutorials
Training Modules
View Presentations
Download Tools
Scan News
Get Jobs
Message Forums
School Forums
Member Directory
   
CONTRIBUTE:
    Sign me up!
Post an Event
Submit Tutorials
Upload Tools
Link News
Post Jobs
   
   
Home >  Tutorials >  General Coding >  Windows XP Visual Styles for Windows Forms
Add to MyHood
   Windows XP Visual Styles for Windows Forms   [ printer friendly ]
Stats
  Rating: 5 out of 5 by 12 users
  Submitted: 09/12/02
Heath Stewart (clubstew@hotmail.com)

 
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. Since then, I've seen several companies like Infragistics boasting that they support Windows XP Visual Styles. After doing some digging, I learned that they really have nothing to boast about!

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

You will need a few things to complete this tutorial:
  1. The Microsoft .NET Framework SDK (required)
  2. Microsoft Visual Studio .NET, which really aids in designing your Windows Forms (optional)
  3. 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.

For those of you not using Visual Studio .NET or for those who haven't completed their form design yet, the code I finished with looks like:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication1
{
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.RadioButton radioButton1;
        private System.Windows.Forms.RadioButton radioButton2;
        private System.Windows.Forms.RadioButton radioButton3;
        private System.Windows.Forms.CheckBox checkBox1;
        private System.Windows.Forms.CheckBox checkBox2;
        private System.Windows.Forms.CheckBox checkBox3;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.TabControl tabControl1;
        private System.Windows.Forms.TabPage tabPage1;
        private System.Windows.Forms.TabPage tabPage2;
        private System.Windows.Forms.ListView listView1;
        private System.Windows.Forms.DateTimePicker dateTimePicker1;
        private System.Windows.Forms.TrackBar trackBar1;
        private System.Windows.Forms.HScrollBar hScrollBar1;
        private System.Windows.Forms.VScrollBar vScrollBar1;
        private System.Windows.Forms.ColumnHeader columnHeader1;
        private System.Windows.Forms.ColumnHeader columnHeader2;
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            InitializeComponent();
        }
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.button2 = new System.Windows.Forms.Button();
            this.button1 = new System.Windows.Forms.Button();
            this.checkBox3 = new System.Windows.Forms.CheckBox();
            this.checkBox2 = new System.Windows.Forms.CheckBox();
            this.checkBox1 = new System.Windows.Forms.CheckBox();
            this.radioButton3 = new System.Windows.Forms.RadioButton();
            this.radioButton2 = new System.Windows.Forms.RadioButton();
            this.radioButton1 = new System.Windows.Forms.RadioButton();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.tabControl1 = new System.Windows.Forms.TabControl();
            this.tabPage1 = new System.Windows.Forms.TabPage();
            this.listView1 = new System.Windows.Forms.ListView();
            this.tabPage2 = new System.Windows.Forms.TabPage();
            this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
            this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
            this.trackBar1 = new System.Windows.Forms.TrackBar();
            this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
            this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
            this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
            this.groupBox1.SuspendLayout();
            this.tabControl1.SuspendLayout();
            this.tabPage1.SuspendLayout();
            this.tabPage2.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
            this.SuspendLayout();
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] {
                this.button2,
                this.button1,
                this.checkBox3,
                this.checkBox2,
                this.checkBox1,
                this.radioButton3,
                this.radioButton2,
                this.radioButton1});
            this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.groupBox1.Location = new System.Drawing.Point(8, 8);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(336, 104);
            this.groupBox1.TabIndex = 0;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "groupBox1";
            // 
            // button2
            // 
            this.button2.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.button2.Location = new System.Drawing.Point(168, 72);
            this.button2.Name = "button2";
            this.button2.TabIndex = 7;
            this.button2.Text = "button2";
            // 
            // button1
            // 
            this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.button1.Location = new System.Drawing.Point(248, 72);
            this.button1.Name = "button1";
            this.button1.TabIndex = 6;
            this.button1.Text = "button1";
            // 
            // checkBox3
            // 
            this.checkBox3.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.checkBox3.Location = new System.Drawing.Point(216, 40);
            this.checkBox3.Name = "checkBox3";
            this.checkBox3.TabIndex = 5;
            this.checkBox3.Text = "checkBox3";
            // 
            // checkBox2
            // 
            this.checkBox2.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.checkBox2.Location = new System.Drawing.Point(112, 40);
            this.checkBox2.Name = "checkBox2";
            this.checkBox2.TabIndex = 4;
            this.checkBox2.Text = "checkBox2";
            // 
            // checkBox1
            // 
            this.checkBox1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.checkBox1.Location = new System.Drawing.Point(8, 40);
            this.checkBox1.Name = "checkBox1";
            this.checkBox1.TabIndex = 3;
            this.checkBox1.Text = "checkBox1";
            // 
            // radioButton3
            // 
            this.radioButton3.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.radioButton3.Location = new System.Drawing.Point(216, 16);
            this.radioButton3.Name = "radioButton3";
            this.radioButton3.TabIndex = 2;
            this.radioButton3.Text = "radioButton3";
            // 
            // radioButton2
            // 
            this.radioButton2.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.radioButton2.Location = new System.Drawing.Point(112, 16);
            this.radioButton2.Name = "radioButton2";
            this.radioButton2.TabIndex = 1;
            this.radioButton2.Text = "radioButton2";
            // 
            // radioButton1
            // 
            this.radioButton1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.radioButton1.Location = new System.Drawing.Point(8, 16);
            this.radioButton1.Name = "radioButton1";
            this.radioButton1.TabIndex = 0;
            this.radioButton1.Text = "radioButton1";
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(8, 120);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(336, 23);
            this.progressBar1.TabIndex = 1;
            // 
            // tabControl1
            // 
            this.tabControl1.Controls.AddRange(
                new System.Windows.Forms.Control[] {
                    this.tabPage1,
                    this.tabPage2});
            this.tabControl1.Location = new System.Drawing.Point(8, 152);
            this.tabControl1.Name = "tabControl1";
            this.tabControl1.SelectedIndex = 0;
            this.tabControl1.Size = new System.Drawing.Size(336, 184);
            this.tabControl1.TabIndex = 2;
            // 
            // tabPage1
            // 
            this.tabPage1.Controls.AddRange(new System.Windows.Forms.Control[] {
                this.listView1});
            this.tabPage1.Location = new System.Drawing.Point(4, 22);
            this.tabPage1.Name = "tabPage1";
            this.tabPage1.Size = new System.Drawing.Size(328, 158);
            this.tabPage1.TabIndex = 0;
            this.tabPage1.Text = "tabPage1";
            // 
            // listView1
            // 
            this.listView1.AutoArrange = false;
            this.listView1.Columns.AddRange(
                new System.Windows.Forms.ColumnHeader[] {
                    this.columnHeader1,
                    this.columnHeader2});
            this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.listView1.Name = "listView1";
            this.listView1.Size = new System.Drawing.Size(328, 158);
            this.listView1.TabIndex = 0;
            this.listView1.View = System.Windows.Forms.View.Details;
            // 
            // tabPage2
            // 
            this.tabPage2.Controls.AddRange(new System.Windows.Forms.Control[] {
                this.vScrollBar1,
                this.hScrollBar1,
                this.trackBar1,
                this.dateTimePicker1});
            this.tabPage2.Location = new System.Drawing.Point(4, 22);
            this.tabPage2.Name = "tabPage2";
            this.tabPage2.Size = new System.Drawing.Size(328, 158);
            this.tabPage2.TabIndex = 1;
            this.tabPage2.Text = "tabPage2";
            // 
            // vScrollBar1
            // 
            this.vScrollBar1.Location = new System.Drawing.Point(304, 8);
            this.vScrollBar1.Name = "vScrollBar1";
            this.vScrollBar1.Size = new System.Drawing.Size(17, 128);
            this.vScrollBar1.TabIndex = 3;
            // 
            // hScrollBar1
            // 
            this.hScrollBar1.Location = new System.Drawing.Point(8, 136);
            this.hScrollBar1.Name = "hScrollBar1";
            this.hScrollBar1.Size = new System.Drawing.Size(296, 17);
            this.hScrollBar1.TabIndex = 2;
            // 
            // trackBar1
            // 
            this.trackBar1.Location = new System.Drawing.Point(8, 40);
            this.trackBar1.Name = "trackBar1";
            this.trackBar1.Size = new System.Drawing.Size(288, 45);
            this.trackBar1.TabIndex = 1;
            // 
            // dateTimePicker1
            // 
            this.dateTimePicker1.Location = new System.Drawing.Point(8, 8);
            this.dateTimePicker1.Name = "dateTimePicker1";
            this.dateTimePicker1.Size = new System.Drawing.Size(288, 20);
            this.dateTimePicker1.TabIndex = 0;
            // 
            // columnHeader1
            // 
            this.columnHeader1.Text = "ColumnHeader1";
            this.columnHeader1.Width = 100;
            // 
            // columnHeader2
            // 
            this.columnHeader2.Text = "ColumnHeader2";
            this.columnHeader2.Width = 100;
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(352, 342);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                this.tabControl1,
                this.progressBar1,
                this.groupBox1});
            this.Name = "Form1";
            this.Text = "Form1";
            this.groupBox1.ResumeLayout(false);
            this.tabControl1.ResumeLayout(false);
            this.tabPage1.ResumeLayout(false);
            this.tabPage2.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
            this.ResumeLayout(false);

        }
        #endregion

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

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:
<?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="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.
  1. Right-click on the root node ("WindowsApplication.exe") and select "Add Resource...".
  2. Click "Import...", browse for "WindowsApplication.exe.manifest" in your project directory, and click "Open".
  3. In the "Resource Type" text box, type RT_MANIFEST and click "OK".
  4. Save all files and go back to your resource view you were previously in. You should now see a folder named "RT_MANIFEST".
  5. 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.
  6. 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.

Return to Browsing Tutorials

Email this Tutorial to a Friend

Rate this Content:  
low quality  1 2 3 4 5  high quality

Reader's Comments Post a Comment
 
Very well written. I'll have to keep this in mind next time I'm playing around and give it a try.
-- Matthew Hildebrand, September 18, 2002
 
very good tutorial heath...a bit beyond my understanding, but i will eventually get there one day. thank you for all that you contribute to the site.
-- J J, September 19, 2002
 
Very good.

Here's a cool tool I found on MSDN that is a VS.NET plug in that does some of the manual steps for you (like changing control's FlatStyle and putting the manifest into a resource) during compilation of the app.

Download tool.
Read Documentation.
-- Pedro Silva, September 19, 2002
 
Hey. Very cool. Thanks a lot, I've been trying to figure some of this stuff out for a while now...
-- Aaron Brethorst, September 20, 2002
 
Very good tutorial
-- Greg Bester, September 20, 2002
 
Keep up-to-date on this article at http://www.codeproject.com/csharp/dotnetvisualstyles.asp.
-- Heath Stewart, February 02, 2003
 
Or you could just add the following line to your Main() procedure:

Application.EnableVisualStyles();

This works in .net Framework 1.1. Not sure if it works in 1.0. You must still set the FlatStyle property to System.
-- Robin Davies, January 01, 2004
 
For very long time I used this method to give my windows forms cool-windows-xp-like-visual-styles. but today I found something much easier... Check this out!
just put this small code in the very top of the "Windows Form Designer generated code" region :

Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New frmMain)
End Sub
-- igal b, November 07, 2004
 
Very Nice tutorial. Just rated 5 :-)
-- Arun V, August 13, 2009
 

Copyright © 2001 DevHood® All Rights Reserved