Click here to Skip to main content
Email Password   helpLost your password?

Introduction

This article is about getting controls found in Windows Vista to make use of the new Windows Vista user interface. Included in the project are some components (Commandlinks, ImageButton, SplitButton) that work just like the Windows Vista themed controls.

The article would aim to achieve most of the interface effects (like the fade-in/out) effects seen throughout Windows Vista.

Background

Most users of Windows Vista would probably notice the new user interface. Each control is a step nicer compared to that of Windows XP, and it comes complete with nice little fade effects. However, Microsoft Visual Studio does not support the full Vista themes by default. Although Visual Studio 2005 attempts to address the visual styles problem, it still does not allow controls to achieve all the visual effects seen throughout Windows Vista.

This article covers on:

It utilizes the user32.dll SendMessage() function, as well as the uxtheme.dll setwindowtheme() function for certain controls in order to render some of the controls to the desired level.

Prerequisites

You will need the following things to complete this tutorial:

Some other useful things (optional):

Common controls

Most of the controls are already ready for the Windows Vista theming. I'm sure you have heard of EnableVisualStyles() right? EnableVisualStyles() is usually called to allow theme-aware controls to gain the user interface theme. While Visual Studio 2005 already has this done, Visual Studio 2003 does not have this on by default. If you want to enable theming for common controls, you can view Heath Steward's article on Windows XP Visual Styles for Windows Forms.

EnableVisualStyles() affects the following controls:

While Visual Studio 2005 supports Visual Theming amongst controls, these controls do not have the "full" theme, which includes the fade effects. This problem can be addressed by setting FlatStyle to System. However, doing this means that images would not be displayed on such controls. This problem can be addressed fairly easily in the next section.

Getting images working on Buttons and other controls

By setting the button's FlatStyle to System makes buttons and some other images fail to display on these buttons. But, this section aims to address this problem, by using as little code as possible.

How to get this done? Well, we need to play around with the SendMessage() function found in user32.dll.

First, we would need to declare the function (but first, you will need to import System.Runtime.InteropServices):

//Imports the user32.dll

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage
            (IntPtr hWnd, int msg, int wParam, int lParam);

To set the image of a control, we will need to use the BM_SETIMAGE [0x00F7] message. For now, we would use an icon (Declared in System.Drawing) as an image, as it is easy to get a handle on the icon.

const int BM_SETIMAGE = 0x00F7;
private Icon buttonicon;
//Sets the button to use an icon

void SetImage()
{
    IntPtr iconHandle = IntPtr.Zero;

    // Get the icon's handle.

    if (this.buttonicon != null)
    {
        iconHandle = this.Icon.Handle;
    }

    //Sets the icon

    SendMessage(this.button1.Handle, BM_SETIMAGE, 1, (int)iconHandle);
}

What this code does is to retrieve the handle of the icon which you want to display on the button (called "button1"), and sends a message to Windows to set the button to use the icon.

You can set what icon you want by setting "buttonicon". You can do so by using the following code:

buttonicon = new Icon(SystemIcons.Exclamation, 40, 40);
SetImage();

This uses the system's exclamation icon. What you would get:

If you would want to use a bitmap/image instead of an icon, you can use the GetHIcon() method from the Bitmap to retrieve the bitmap's handle and use the handle to set the button's image.

IntPtr iconhandle = IntPtr.Zero;
Bitmap image = new Bitmap("C:\images\an_image.png");
iconhandle = image_.GetHicon();
SendMessage(this.Handle, VistaConstants.BM_SETIMAGE, 1, (int)iconhandle);

This button still supports the fade effects other normal buttons have.

However, there is one small problem associated with using this method. If this button's text is set to "", no image would be displayed. This problem can be solved by using the createParams() function and assigning the BS_ICON theme to the button.

//CreateParams property

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cParams = base.CreateParams;
        if (this.ShowIconOnly == true)
        {
            //Render button without text

            cParams.Style |= 0x00000040; // BS_ICON value

        }
    return cParams;
    }
}

This method is best done from a class which is inherited from button.

CommandLinks

CommandLinks are really just buttons, assigned with a different theme. Their themes and their values (taken from CommCtrl.h in the Windows Vista SDK) are as follows:

The first step would be to create a class inherited from button. Then, we can override the CreateParams() function to make the button use the respective theme. For the theme to take effect, you would need to set the button's flatstyle to system. Below is the class for the CommandLink:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices

public class CommandLink : Button
{
    const int BS_COMMANDLINK = 0x0000000E;

    //Set button's flatstyle to system

    public CommandLink()
    {
        this.FlatStyle = FlatStyle.System;
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cParams = base.CreateParams;
            //Set the button to use Commandlink styles

            cParams.Style |= BS_COMMANDLINK;
            return cParams;
        }
    }
}

You can then build the project and use the component in your Windows Forms just like a normal button (since it is inherited from a normal button). The CommandLink looks like:

*The mouse is over the CommandLink, but PrintScreen would not capture the mouse.

The button supports the fade effects just like the actual controls.

But wait? where's the CommandLink's "note"? Well, we can implement that feature by sending the BCM_SETNOTE [0x00001609] message to Windows. We can incorporate it into a property to set the note of the CommandLink with ease.

const uint BCM_SETNOTE = 0x00001609;
//Imports the user32.dll

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr SendMessage
        (HandleRef hWnd, UInt32 Msg, IntPtr wParam, string lParam);
//Note property

private string note_ = "";
public string Note
{
    get
    {
        return this.note_;
    }
    set
    {
        this.note_ = value;
        this.SetNote(this.note_);
    }
}

//Sets the button's note

void SetNote(string NoteText)
{
    //Sets the note

    SendMessage(new HandleRef(this, this.Handle), 
                BCM_SETNOTE, IntPtr.Zero, NoteText);
}

You would get:

You can also use the same method for showing icons/images on Buttons for CommandLinks:

SplitButtons

Just like CommandLinks, SplitButtons are just simply buttons. You can set its style to that of the SplitButton's using the CreateParams method:

However, even after setting the style, how are you going to associate a menu (contextmenu) to the button? We can do this by first associating an event which would be fired whenever a person clicks on the "dropdown" on the splitbutton. First, we would listen to all messages sent to the button by overriding the wndproc() method. It happens that the BCN_SETDROPDOWNSTATE [0x1606] message would be sent whenever the dropdown is clicked. This message is fired several times, but only one of the messages happen to be unique, with WPARAMS having the value of "1". The filtering of messages is best done within another class. This sample code would fire a custom event (DropDown_Clicked) whenever the dropdown is pushed.

protected override void WndProc(ref Message m)
{
    // Listen for operating system messages; 

    // Filter out a lot of messages here

    //The dropdown glyph changes:

    //Mousedown (at dropdown area) => Dropdown Event fired 

    //                => Glyph changes => MouseUp => Glyph Changes

    switch (m.Msg)
    {
        case (VistaControls.VistaConstants.BCM_SETDROPDOWNSTATE):
        //PROBLEM: other buttons also have would encounter this message

        if (m.HWnd == this.Handle)
        {
            ////This message seems to occur when the drop down is clicked; 

            ////Occurs several times, but one of them have the value of 1 

            ////in WParams

            if (m.WParam.ToString() == "1")
            {
                DropDown_Clicked();
            }
        }
    break;
    }

    base.WndProc(ref m);
}

Using this custom event, we can show a contextmenu whenever the dropdown part of the button is pressed (full code in the demo). This isn't all though. We have only assigned an event that would be fired whenever the Dropdown is pushed. We would need to make the dropdown glyph change at the right time. There are a few messages that we can use to achieve the correct painting of the glyphs. They are the WM_PAINT [0x0F], WM_LBUTTONDOWN [0x201], WM_MOUSELEAVE [0x2A3], WM_LBUTTONUP [0x202] and WM_KILLFOCUS [0x08] messages. We can run code whenever these messages are sent by overriding the WndProc() message. (The code is too messy to be placed here, but the full code can be found via the Windows Vista Controls Demo.)

This control also supports the fade-effects.

Cue TextBoxes

Some TextBoxes in Windows Vista hint the user what they should type in (e.g. the search box). It usually appears as some grey text on the text box that would disappear when the user attempts to type things into the textbox. This feature is know as "cue banner". You can enable this feature on a textbox by using the EM_SETCUEBANNER [0x1501] message.

SendMessage(textbox1.Handle, 0x1500 + 1, IntPtr.Zero, 
                "Please type in something.");

Mainmenus and Contextmenus

The default MainMenus (or MainMenuStrip) and ContextMenus (or ContextMenuStrip) in Visual Studio 2005 do not fully support the Windows Vista theme:

If you want to get the Windows Vista theme on your main menus and context menus, you would need to use the Visual Studio 2003 version, or the backwards compatible version on Visual Studio 2005 (Called "MainMenu" and "ContextMenu").

You can assign ContextMenus to controls using it's ContextMenu property (might be hidden in VB.NET in Visual Studio 2005).

Toolbars

While the default toolbars in Visual Studio 2005 do have the Windows Vista look (if the Rendermode is set to System), it does not have all of it. Most toolbars on Windows Vista have the fade effects. To get it, you will need to use the Visual Studio 2003 version or the backwards compatible version on Visual Studio 2005 (and above), and set its Appearance as Flat to get the fade effects.

You can use ImageLists on toolbar buttons as well. For Toolbars to use the ImageList properly in Visual Studio 2003, call the applications.DoEvents() function after the application.EnableVisualStyles() function (Bugfix for Application.EnableVisualStyles Bug by Don Kackman).

Progressbars

In Windows Vista, progressbars come in different flavors, the most common progressbar being the green one. However, there are also the red and yellow versions as well (there is a blue version, known as a meter, but that is inaccessible). The progressbar colors seem to correspond to specific progressbar states. You can set these states using the PBM_SETSTATE [0x40F] message. The states are PBST_NORMAL [0x0001], PBST_ERROR [0x0002] and PBST_PAUSE [0x0003].

SendMessage(progressbar1.Handle, 0x400 + 16, 0x0001, 0); //Normal; Green

SendMessage(progressbar1.Handle, 0x400 + 16, 0x0002, 0); //Error; Red

SendMessage(progressbar1.Handle, 0x400 + 16, 0x0003, 0); //Pause; Yellow

TreeViews and ListViews

By default, TreeViews and ListViews do not have the same look as that of Explorer:

However, with a bit of code, you can make it look like this:

You would need to use the SetWindowTheme() function found in the UXTheme.dll file. You can do this by using the following code:

//Imports the UXTheme DLL

[DllImport("uxtheme", CharSet = CharSet.Unicode)]
public extern static Int32 SetWindowTheme
        (IntPtr hWnd, String textSubAppName, String textSubIdList);

Then, you can set the relevant control to use the styles by using the following code:

SetWindowTheme(listView1.Handle, "explorer", null);

Where "listView1" is your ListView. You can do this for TreeViews as well.

But there is more. In Windows Explorer, these ListViews have the semi-transparent selection as well. You can do this by calling the LVS_EX_DOUBLEBUFFER [0x00010000] extended style.

SendMessage(listview1.Handle, 0x1000 + 54, 0x00010000, 0x00010000);

Treeviews in Windows Explorer also have the fade effects. This can be achieved via the TVS_EX_FADEINOUTEXPANDOS [0x0040] extended style.

SendMessage(treeview1.Handle, 0x1100 + 44, 0x0040, 0x0040);

The treeviews also have the "auto-scroll" feature. You can enable this via the TVS_EX_AUTOHSCROLL [0x0020] extended style.

SendMessage(treeview1.Handle, 0x1100 + 44, 0x0020, 0x0020);

Points of Interest

There might be several messages or functions that can be used to modify the theme of controls that may not be found in the limited documentation on Windows Vista. Of course, it is kind of unusual that we have to use older versions of controls (like MainMenu and ContextMenu) in order to achieve the full potential of the new Windows Vista graphical user interface.

Things of note

I have not tested the above codes on Visual Studio 2003, nor have I run the application on Windows XP (I didn't make it backwards compatible "yet").

Some custom controls in the demo that may not work on legacy Windows versions are the CommandLinks, SplitButtons and ProgressBars.

It was tested in Visual Studio 2005 and Windows Vista.

References

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralUse spesific theme
BlackDogSpark
7:44 22 Oct '09  
Is there away to select what theme to use? I mean so that I can use different theme on the app and not the one that is currently in use.
GeneralListView corrected tricky Enter Event
Der M
12:28 21 Feb '09  
Here is my solution to your ExplorerListView. I have removed the enter event workaround and now it works pretty good.


    public class ExplorerListView: ListView
{
private const int LVM_FIRST = 0x1000; //Value from http://www.winehq.org/pipermail/wine-devel/2002-October/009527.html
private const int LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54;
private const int LVS_EX_DOUBLEBUFFER = 0x00010000;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
//Imports the UXTheme DLL
[DllImport("uxtheme", CharSet = CharSet.Unicode)]
private extern static Int32 SetWindowTheme(IntPtr hWnd, String textSubAppName, String textSubIdList);

protected override void InitLayout()
{
base.InitLayout();


SetWindowTheme(this.Handle, "explorer", null); //Explorer style
SendMessage(this.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_DOUBLEBUFFER); //Blue selection
}
}

QuestionExplorerListView class Load event
barry@barrykaye.net
2:22 10 Feb '09  
In the download sourcecode file ExplorerListView.cs Load event you use the line:
SendMessage(this.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_DOUBLEBUFFER); //Blue selection
However, in the Main.cs example line 316 you use the line:
VistaControls.VistaConstants.SendMessage(lv1.Handle, VistaControls.VistaConstants.LVM_SETEXTENDEDLISTVIEWSTYLE, VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER, VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER);
I note the difference in the 3rd parameter between 0 and VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER - which is correct please?
GeneralExplorerListView - FullRowSelect [modified]
Dead Dave
17:00 26 Jan '09  
FullRowSelect does not work with your ExplorerListView in Details View. Here is the solution:

public ExplorerListView()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();

this.Enter += new EventHandler(ExplorerListView_Load);
}

modified on Tuesday, January 27, 2009 7:06 PM

GeneralRe: ExplorerListView - FullRowSelect
zicarius
14:56 7 Feb '09  
Solution to use if FullRowSelect does not work:

public class ExplorerListView: ListView
{
...
public const int LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 36;
...
}
GeneralI've read the note, but..
harold aptroot
3:41 20 Jan '09  
SplitButton and CommandLink don't work on XP, they don't show up at all. What would it take to fix that? (eg make them fall back to a regular button?)


GeneralRe: I've read the note, but..
Dead Dave
13:45 27 Jan '09  
Check if the OS version (Major) is > 5 before applying Vista specific code.
Generaldetailed listview without vertical lines [modified]
Torbinho
0:46 26 Oct '08  
is it possible to hide the vertical line when I use a detailed listview with vista explorer style?
maybe we can change the color of these lines?

edit:
I fixed it myself: by using a background image the vertical gridlines of the vista explorer style disapeared

modified on Monday, October 27, 2008 3:14 PM

QuestionVista Style Group/Sort anybody?
Alexandru Stanciu
18:57 27 Feb '08  
Any idea on how to get something like the Windows Vista Explorer ListView with the nice per column Sort/Group feature? Roll eyes
GeneralRe: Vista Style Group/Sort anybody? [modified]
Nicholas Kwan
0:40 2 Mar '08  
You can do that via Visual Studio, using the designer.

modified on Sunday, March 2, 2008 5:57 AM

QuestionLicence
Julian-w
5:22 30 Dec '07  
Hello,
first: your project is great!!!

My Question:
I program an openSource control library, them all controls of Windows Vista contains. I would use your sourcecode with a little modification (only namespace and class-name) control library.
Can I do this?

My Site: julian-w.de

(Sorry for my bad English, I'm from Germany)

GeneralRe: Licence
Nicholas Kwan
0:05 24 Feb '08  
You can do what ever you want to the code, integrate it, put it in some product, etc. After all, isn't that the point of this article? Wink
GeneralRe: Licence
Julian-w
0:09 24 Feb '08  
Thank you for the answere.

My Site: julian-w.de

(Sorry for my bad English, I'm from Germany)

GeneralUsing icons on a Vista menu
logan1337
6:41 28 Dec '07  
Does anyone know how to add icons to the menu items of a Vista menu? Currently I'm using ToolStrips in .NET but they look awful under Vista, and would like to use the standard system menus. I can switch to an old-fashioned (vs2003) MainMenu control, but its items do not support icons and therefore isn't good enough, as almost all of my menu items have icons.

I've noticed in explorer (e.g. in the "Organize" menu) that these system menus do in fact support icons... the question is how to get this from .NET.

Even if I have to use Win32 interop, how might this be accomplished? Any ideas?

{o,o}.oO( Did somebody say MouseDown? )
|)””’)
-”-”-

GeneralRe: Using icons on a Vista menu
Nicholas Kwan
0:11 24 Feb '08  
If Microsoft were to provide more documentation... then this would have been much easier. I do not have any method for showing icons in toolstrips. However, it does seem that Microsoft used a similar technique for context menus in Windows XP.
AnswerUsing icons on a Vista menu (C# solution)
wyDay
8:10 17 May '08  
I've worked out a solution, and posted an article about it: Vista Menu with Icons in C#.


VistaMenu is open source and the article explains how to use it.

-Wyatt
GeneralRe: Using icons on a Vista menu (C# solution)
logan1337
8:13 17 May '08  
Cool! Thanks for the note!

“Time and space can be a bitch.”
–Gushie, Quantum Leap
{o,o}.oO( Looking for a great RSS reader? Try FeedBeast! )
|)””’)            Built with home-grown CodeProject components! -”-”-

GeneralThanks! Any support for Task Dialogs?
Neo-Code
23:11 26 Dec '07  
Thank you so much for this article! It has brought great ease to Vista-ificating my applications. I have googled for over 2 hours for how to make a Task Dialog in VB.NET, with no real results. Microsoft say it replaces the Messagebox.show() function, so why isn't it easy to use like the messagebox is? I have found a few class implementations but these are fake dialogs which use icons from the Resources namespace.... basically just a form which looks like a Task Dialog which the label changes on. Any help is greatly appreciated.


Regards
GeneralRe: Thanks! Any support for Task Dialogs?
Jereck
1:59 9 Feb '08  
Maybe you should have a look to Daniel Moth's wrapper class :
http://www.danielmoth.com/Blog/2006/06/vista-taskdialog.html[^]
GeneralYou are a true life saver - 5 stars
Prone2Moan
4:24 16 Nov '07  
*****
Well done
GeneralThese problems shouldn't exist!
Dmitri Nesteruk
3:44 1 Oct '07  
I remember the time when XP came out and, if you wanted to get themes to work you had to edit some manifest, and even then it wasn't 100% reliable. I can't recall if it was in MFC or not, but the point is that, several years on, Microsoft is still preventing people from taking full advantages of the latest UI features of its operating systems. I kind of get the feeling that this might be deliberate. Very frustrating! Cry
GeneralRe: These problems shouldn't exist!
Nicholas Kwan
4:15 1 Oct '07  
Well, that's true. I guess it is one of Microsoft's ways to make its applications look more better than others. Smile
QuestionTreeview flash when fade in/out.
XiaoFaye
17:41 5 Sep '07  
this treeview is cool!

but it will flash when it fade in/out, not like Explorer in Vista, how can I solve this?? Thanks.
AnswerRe: Treeview flash when fade in/out.
XiaoFaye
20:03 5 Sep '07  
public const int TVS_EX_DOUBLEBUFFER = 0x0004;

Add this style is OK.
GeneralRe: Treeview flash when fade in/out.
Nicholas Kwan
21:33 6 Sep '07  
You can add this extended style manually by calling a certain function (calling a message to TVM_SETEXTENDEDSTYLE).
However, it has no effect on the flicker. The flicker is a known issue, but it is not known why it occurs. It occurs at random.
*Upon adding this style, the flicker still occurs, though maybe less frequent.


Last Updated 17 Jun 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010