|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis 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 ( The article would aim to achieve most of the interface effects (like the fade-in/out) effects seen throughout Windows Vista. BackgroundMost 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 PrerequisitesYou 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
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 Getting images working on Buttons and other controlsBy setting the How to get this done? Well, we need to play around with the First, we would need to declare the function (but first, you will need to import //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 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 You can set what buttonicon = new Icon(SystemIcons.Exclamation, 40, 40);
SetImage();
This uses the system's exclamation
If you would want to use a bitmap/image instead of an icon, you can use the 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 However, there is one small problem associated with using this method. If this //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 CommandLinks
The first step would be to create a class inherited from 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
*The mouse is over the The But wait? where's the 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
SplitButtons
Just like
However, even after setting the style, how are you going to associate a menu (contextmenu) to the 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
This control also supports the fade-effects. Cue TextBoxesSome SendMessage(textbox1.Handle, 0x1500 + 1, IntPtr.Zero,
"Please type in something.");
Mainmenus and ContextmenusThe default
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 " You can assign ToolbarsWhile the default
You can use ProgressbarsIn Windows Vista, 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 ListViewsBy default,
However, with a bit of code, you can make it look like this:
You would need to use the //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 " But there is more. In Windows Explorer, these SendMessage(listview1.Handle, 0x1000 + 54, 0x00010000, 0x00010000);
SendMessage(treeview1.Handle, 0x1100 + 44, 0x0040, 0x0040);
The SendMessage(treeview1.Handle, 0x1100 + 44, 0x0020, 0x0020);
Points of InterestThere 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 Things of noteI 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 It was tested in Visual Studio 2005 and Windows Vista. References
History
| ||||||||||||||||||||