|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Downloads
Sample application using custom controls (Button, CheckBox, RadioButton, ProgressBar, etc.) drawn with the wrapper.
IntroductionIt's been a long time since I became a member of The Code Project. I've learned a lot and it's time for me to share my knowledge. I think this is not the first time you are reading an article on an uxtheme wrapper. Like me, you have probably done a lot of Googling, seeking information and C# samples about uxtheme (also known as Visual Styles or Windows themes) and found nothing that matches what you want. However, there are many great articles on The Code Project, like "A Managed C++ Wrapper Around the Windows XP Theme API" by Don Kackman or "Add XP Visual Style Support to OWNERDRAW Controls" by David Zhao and "Themed Windows XP style Explorer Bar" by Mathew Hall, which describe visual styles and provide useful tips. But, in my point of view, they were not designed for a generic C# usage and they don't offer a simple way to use visual styles in our applications. I wanted to have a way to enumerate and switch between available themes on a computer, so I decided to make my own C# wrapper. The articleSo, how does this work? I've split this artcile in three parts:
Background needsHere are the features I wanted to find in a wrapper:
FeaturesWhat you will find in this sample:
You will also find custom Designers/Editors if you want to learn how to create your own design-time support. I - Visual Style and UxTheme.dllI will not explain how the uxtheme.dll works, I do not have enough space in this article (an I'm not going to rewrite the msdn). The interesting thing is how to write a C# wrapper. The principle is quite simple: find the dll (or module) you want to handle, seek its function's signatures, and then write them in a C# equivalent form. The uxtheme function's signatures are defined in the uxtheme.h file, and enumerations/constants in the tmschema.h file. Those files are located in "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include" directory if you're using VS 2003. In uxtheme.h, you'll find something like: //-----------------------------------------------------------------------
// DrawThemeText() - draws the text using the theme-specified
// color and font for the "iPartId" and
// "iStateId".
//
// hTheme - theme data handle
// hdc - HDC to draw into
// iPartId - part number to draw
// iStateId - state number (of the part) to draw
// pszText - actual text to draw
// dwCharCount - number of chars to draw (-1 for all)
// dwTextFlags - same as DrawText() "uFormat" param
// dwTextFlags2 - additional drawing options
// pRect - defines the size/location of the part
//-----------------------------------------------------------------------
THEMEAPI DrawThemeText(HTHEME hTheme, HDC hdc, int iPartId,
int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags,
DWORD dwTextFlags2, const RECT *pRect);
The next step is to write the C# equivalent method. For example, the
/// <summary>
/// Draws text using the color and font defined by the visual style.
/// </summary>
/// <param name="hTheme">Handle to a window's specified
/// theme data.</param>
/// <param name="hdc">Handle to a device context (HDC) used for
/// drawing the theme-defined background image.</param>
/// <param name="iPartId">Value that specifies the part to draw.</param>
/// <param name="iStateId">Value that specifies the state of the
/// part to draw.</param>
/// <param name="pszText">Pointer to a string that contains the text
/// to draw.</param>
/// <param name="iCharCount">Value that contains the number of
/// characters to draw. If the parameter is set to -1, all
/// the characters in the string are drawn.</param>
/// <param name="dwTextFlags">A bitwise combination
/// of <see cref="TextFormatFlags"/> values to specify the text
/// formatting.</param>
/// <param name="dwTextFlags2">Not used. Set to 0.</param>
/// <param name="pRect">Pointer to a RECT structure that contains
/// the rectangle, in logical coordinates, in which the text
/// is to be drawn.</param>
[DllImport("UxTheme.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern System.Int32 DrawThemeText(
IntPtr hTheme,
IntPtr hdc,
UInt32 iPartId,
UInt32 iStateId,
String pszText,
Int32 iCharCount,
UInt32 dwTextFlags,
UInt32 dwTextFlags2,
ref RECT pRect
);
When translating a function, you need to use the There are many other optional parameters for the To get the last win32 error, you can use the following code sample: //using System.Runtime.InteropServices;
//using System.ComponentModel;
//...
// call an imported function using SetLastError=true before
// using this piece of code
int errorCode = Marshal.GetLastWin32Error();
Console.WriteLine("The last win32 error code was: "+errorCode);
// depends on the called function's error codes
if(errorCode < 0) throw new Win32Exception(errorCode);
The next table provides quick equivalents between c++ types and C# :
Most of the other c++ types can be translated as II - Visual Style philosophyA Theme can be defined as UI properties grouped by a "Color scheme" and a "Size scheme". Then, a theme is retrieved by its color and size scheme. Those properties are dispatched into three files:
Theme's folder treeBasically, available themes are located in "%windir%\Resources\Themes" directory, as shown below :
Each .theme file has its own directory, and a .msstyles file with the same name (eg. panther.theme has its .msstyles file in the directory named panther). You will also find inside the theme's directory a folder named shell, which has a folder for each theme's scheme. Finally, scheme's directory contains a shellstyle.dll. You can also find bitmaps (like wallpapers) or other resources referenced by the shellstyle.dll in this directory. .theme fileA .theme file is an initialization file, with sections and key/value pairs defining many informations. The following sample shows the content of a .theme file. [Theme]
; Recycle Bin
[CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon]
full=%SystemRoot%\SYSTEM32\shell32.dll,32
empty=%SystemRoot%\SYSTEM32\shell32.dll,31
[Control Panel\Desktop]
Wallpaper=%WinDir%Resources\Themes\Panther\Wallpaper\Aqua_Blue.jpg
TileWallpaper=0
WallpaperStyle=2
Pattern=
ScreenSaveActive=0
The interesting section is [VisualStyles]. You'll find in it three important tips : the relative path to the .msstyles file (Path), the color scheme used by the theme (ColorStyle) and the size behavior (Size). Note: if you don't have the %ResourceDir% defined in the environment variables, you can use the sample code below : System.Collections.IDictionary vars =
System.Environment.GetEnvironmentVariables();
// extract the "Path" value
System.Text.StringBuilder val =
new System.Text.StringBuilder(MAX_PATH); // MAX_PATH = 255
Kernel32.GetPrivateProfileString(sectionName, keyName, "", val,
MAX_PATH, iniFile); // MAX_PATH = 255
// remove comments
String path = val.ToString();
if(path.IndexOf(";") != -1) path = path.Substring(0,
result.IndexOf(";"));
path = path.Replace("%WinDir%", @"%windir%\");
path = path.Replace(@"\\", @"\");
path = path.Replace("%ResourceDir%", @"%windir%\Resources");
path = path.Replace("%windir%", Convert.ToString(vars["windir"]));
.msstyles fileA .msstyles file is basically a PE file (eg. a DLL). What we are looking for is in the resource section, under the TEXTFILE and BITMAP resource directories. Note: You can use a software like ResEdit to explore your .msstyles file.
The most important file is THEME_INI. It gives use :
If we use the informations [VisualStyles]
Path=%ResourceDir%\Themes\Panther\Panther.msstyles
ColorStyle=NormalColor
Size=NormalSize
specified in the .theme file, we will find our reference tips into the section named [File.]["color scheme"]["theme name"] like [File.Normalpanther]
ColorSchemes = panther
Sizes = NormalSize
In our example, the .ini file which contains the theme datas is named NORMALPANTHER_INI and the prefix value is set in the ColorSchemes key (the bitmap's names will start with PANTHER). The theme data initialization fileThese files contain informations for each class and parts of the visual style. After reading numerous of this kind of file, section's rules seem to be :
Then, if you want the checkbox data you will have to look in the section [Button.Checkbox] or [button.checkbox]. shellstyle.dllThe article of Mathew Hall describes the internals of this file. If you are interested in understanding it, look "Themed Windows XP style Explorer Bar" his article in The Code Project. III - The wrapperThe following figure describes how the wrapper is designed :
A quick description :
I'm not going to enumerate all the methods provided by each classes because it's not the topic. I will focus on VisualStyleFileThis class is the more important one : its role is to provide an object representation of a Theme. It's also a component that can be shared among your custom controls. It retrieves the visual style's information through a .theme file, eg. it retrieves the theme's .mssstyles, maps the used .ini files and then maps the theme's properties into eight structures :
So, if you want to access a Theme's raw information/data, you just have to create an new // create a new VisualStyleFile
String themeFile = @"C:\WINDOWS\Resources\Themes\Luna.theme";
using(VisualStyleFile theme = new VisualStyleFile(themeFile))
{
// get the documentation informations
VisualStyleDocumention doc = theme.Documentation;
Console.WriteLine(doc.Author + " - " + doc.Copyright);
// get the color/size scheme
Console.WriteLine("Color scheme: "+theme.ThemeSchemeName);
Console.WriteLine("Size scheme: "+theme.ThemeSizeName);
// get the properties of a component
VisualStyleProperties buttonProps = theme.GetElementProperties(
"BUTTON", (uint)ButtonPart.PushButton);
Console.WriteLine(
"Button is transparent : "+buttonProps.Transparent);
Console.WriteLine("Background image: "+buttonProps.ImageFile);
// etc...
}
Using the codeI know, it is quite tedious. But the good news are that all you've read is implemented in this sample. I built this part as an FAQ, maybe you'll find what you want to know. How to enumerate installed theme filesString[] themes = VisualStyleInformation.GetThemeFiles();
foreach(String theme in themes)
{
Console.WriteLine(theme);
}
How to get a theme informationIf you want the current visual style information : // Documentation properties
Console.WriteLine(
"Current theme file: "+VisualStyleInformation.CurrentThemeFileName);
Console.WriteLine(
"Application themed? "+VisualStyleInformation.IsApplicationThemed);
Console.WriteLine("Current theme author: "+VisualStyleInformation.Author);
Console.WriteLine("Current theme company: "+VisualStyleInformation.Company);
// etc...
// Theme raw properties for a "Button"
VisualStyleRenderer renderer = VisualStyleRenderer("BUTTON",
(uint)ButtonPart.PushButton, (uint)PushButtonState.Normal);
// bool properties
bool isButtonTransparent = renderer.GetBoolean(BooleanProperty.Transparent);
bool isBacgroundFilled = renderer.GetBoolean(BooleanProperty.BackgroundFill);
// Color properties
Color borderColor = renderer.GetColor(ColorProperty.BorderColor);
Color fillColor = renderer.GetColor(ColorProperty.FillColor);
Color textColor = renderer.GetColor(ColorProperty.TextColor);
// String properties
String backgroundImage = GetFilename(FilenameProperty.ImageFile);
String glyph = GetFilename(FilenameProperty.GlyphImageFile);// for combo or
// caption button
// etc...
If you want the properties for a specific theme (not the current one) : String themeFile = @"C:\WINDOWS\Resources\Themes\Luna.theme";
using(VisualStyleFile theme = new VisualStyleFile(themeFile))
{
// get the documentation informations
VisualStyleDocumention doc = theme.Documentation;
Console.WriteLine(doc.Author + " - " + doc.Copyright);
// get the color/size scheme
Console.WriteLine("Color scheme: "+theme.ThemeSchemeName);
Console.WriteLine("Size scheme: "+theme.ThemeSizeName);
// get the properties of a component
VisualStyleProperties buttonProps = theme.GetElementProperties("BUTTON",
(uint)ButtonPart.PushButton);
Console.WriteLine("Button is transparent : "+buttonProps.Transparent);
Console.WriteLine("Background image: "+buttonProps.ImageFile);
// etc...
}
Note: Even for the current theme, my preference is the second solution. How to extract a theme .ini files// save the .ini files of a specific theme
String themeFile = @"C:\WINDOWS\Resources\Themes\Luna.theme";
String savePath = Environment.CurrentDirectory + @"\inifiles\";
using(VisualStyleFile theme = new VisualStyleFile(themeFile))
{
theme.SaveIniFiles(savePath);
}
How to get a theme's bitmap// gets an identified bitmap
String themeFile = @"C:\WINDOWS\Resources\Themes\Luna.theme";
String savePath = Environment.CurrentDirectory;
using(VisualStyleFile theme = new VisualStyleFile(themeFile))
{
// gets the properties
VisualStyleProperties buttonProps = theme.GetElementProperties("BUTTON",
(uint)ButtonPart.PushButton);
// save the bitmap to disk
using(Bitmap bmp = theme.GetBitmap(buttonProps.ImageFile))
{
bmp.Save(savePath+@"\buttonBitmaps.bmp");
}
}
How to share a theme among your custom controlsHow to use a theme's data (not the current one) with your custom control? You just have to add a
Then, set the
How to create your custom rendererImplementation is up to you : it depends on what you want to paint (eg. a listview header, a button, a scrollbar, a caption, etc.). The tip is to clearly separate the painting behavior from the component logic. My point of view is to create your custom controls as a "bean" which computes the right values (bounds, sizes, etc.) and pass them as parameters to your renderer methods. Let's have a 15 minutes tutorial : create a renderer for a window's caption button.
The public enum WindowButtonType : int
{
CloseButton = (int)WindowPart.CloseButton,
MaxButton = (int)WindowPart.MaxButton,
MinButton = (int)WindowPart.MinButton,
HelpButton = (int)WindowPart.HelpButton,
RestoreButton = (int)WindowPart.RestoreButton,
SysButton = (int)WindowPart.SysButton
};
/// <summary>
/// Provides methods for drawing a WindowButton control (eg. Help, Close,
/// Minize, etc.).
/// </summary>
public sealed class WindowButtonRenderer
{
/// <summary>
/// Gets a value indicating whether the WindowButtonRenderer class
/// can be used to draw a window button control with visual styles.
/// </summary>
public static bool IsSupported
{
get
{
return VisualStyleInformation.IsApplicationThemed;
}
}
private WindowButtonRenderer(){ }
// ...
}
/// <summary>
/// Provides methods for drawing a WindowButton control (eg. Help, Close,
/// Minize, etc.).
/// </summary>
public sealed class WindowButtonRenderer
{
/// <summary>
/// Gets a value indicating whether the WindowButtonRenderer class
/// can be used to draw a window button control with visual styles.
/// </summary>
public static bool IsSupported
{
get
{
return VisualStyleInformation.IsApplicationThemed;
}
}
private WindowButtonRenderer(){ }
#region Methods
#region Misc
/// <summary>
/// Gets a VisualStyleRenderer for the specified button state.
/// </summary>
/// <param name="button">The button type.</param>
/// <param name="state">The button state.</param>
private static VisualStyleRenderer GetButtonRenderer(
WindowButtonType button, WindowButtonState state)
{
switch(state)
{
case WindowButtonState.Normal:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Normal);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Normal);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Normal);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Normal);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Normal);
case WindowButtonState.Hot:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Hot);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Hot);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Hot);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Hot);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Hot);
case WindowButtonState.Pushed:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Pressed);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Pressed);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Pressed);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Pressed);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Pressed);
case WindowButtonState.Disabled:
default:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Disabled);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Disabled);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Disabled);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Disabled);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Disabled);
}
}
/// <summary>
/// Gets a <see cref="VisualStyleRenderer"> for the specified
/// button state.
/// </summary>
/// <param name="style">The visual style file to use.</param>
/// <param name="button">The button type.</param>
/// <param name="state">The button state.</param>
private static VisualStyleRenderer GetButtonRenderer(
VisualStyleFile style, WindowButtonType button,
WindowButtonState state)
{
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.GetElement(
style, state));
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.GetElement(
style, state));
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.GetElement(
style, state));
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.GetElement(
style, state));
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.GetElement(
style, state));
}
#endregion
#region Drawing
public static void DrawButton(Graphics g, Rectangle bounds,
WindowButtonType button, WindowButtonState state)
{
if(!IsSupported) throw new InvalidOperationException();
VisualStyleRenderer renderer = GetButtonRenderer(button, state);
if(renderer != null) renderer.DrawBackground(g, bounds);
}
/// <summary>
/// Draws a window Close button control in the specified state
/// and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawCloseButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.CloseButton, state);
}
/// <summary>
/// Draws a window Help button control in the specified state and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawHelpButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.HelpButton, state);
}
/// <summary>
/// Draws a window Minize button control in the specified state
/// and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawMinizeButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.MinButton, state);
}
/// <summary>
/// Draws a window Maximize button control in the specified state
/// and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawMaximizeButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.MaxButton, state);
}
/// <summary>
/// Draws a window Restore button control in the specified state
/// and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawRestoreButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.RestoreButton, state);
}
#endregion
#endregion
}
</see>
/// <summary>
/// Provides methods for drawing a WindowButton control (eg. Help, Close,
/// Minize, etc.).
/// </summary>
public sealed class WindowButtonRenderer
{
/// <summary>
/// Gets a value indicating whether the WindowButtonRenderer class
/// can be used to draw a window button control with visual styles.
/// </summary>
public static bool IsSupported
{
get
{
return VisualStyleInformation.IsApplicationThemed;
}
}
private WindowButtonRenderer(){ }
#region Methods
#region Misc
/// <summary>
/// Gets a VisualStyleRenderer for the specified button state.
/// </summary>
/// <param name="button">The button type.</param>
/// <param name="state">The button state.</param>
private static VisualStyleRenderer GetButtonRenderer(
WindowButtonType button, WindowButtonState state)
{
switch(state)
{
case WindowButtonState.Normal:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Normal);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Normal);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Normal);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Normal);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Normal);
case WindowButtonState.Hot:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Hot);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Hot);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Hot);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Hot);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Hot);
case WindowButtonState.Pushed:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Pressed);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Pressed);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Pressed);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Pressed);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Pressed);
case WindowButtonState.Disabled:
default:
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.Disabled);
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.Disabled);
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.Disabled);
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.Disabled);
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.Disabled);
}
}
/// <summary>
/// Gets a <see cref="VisualStyleRenderer"> for the specified
/// button state.
/// </summary>
/// <param name="style">The visual style file to use.</param>
/// <param name="button">The button type.</param>
/// <param name="state">The button state.</param>
private static VisualStyleRenderer GetButtonRenderer(
VisualStyleFile style, WindowButtonType button,
WindowButtonState state)
{
if(button == WindowButtonType.CloseButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.CloseButton.GetElement(
style, state));
else if(button == WindowButtonType.MaxButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MaxButton.GetElement(
style, state));
else if(button == WindowButtonType.MinButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.MinButton.GetElement(style,state));
else if(button == WindowButtonType.HelpButton)
return new VisualStyleRenderer(
VisualStyleElement.Window.HelpButton.GetElement(style,state));
else return new VisualStyleRenderer(
VisualStyleElement.Window.RestoreButton.GetElement(style,state));
}
#endregion
#region Drawing
public static void DrawButton(Graphics g, Rectangle bounds,
WindowButtonType button, WindowButtonState state)
{
if(!IsSupported) throw new InvalidOperationException();
VisualStyleRenderer renderer = GetButtonRenderer(button, state);
if(renderer != null) renderer.DrawBackground(g, bounds);
}
public static void DrawButton(VisualStyleFile style, Graphics g,
Rectangle bounds, WindowButtonType button, WindowButtonState state)
{
if(!IsSupported) throw new InvalidOperationException();
VisualStyleRenderer renderer = GetButtonRenderer(style, button,
state);
if(renderer != null) renderer.DrawBackground(g, bounds);
}
/// <summary>
/// Draws a window Close button control in the specified state
/// and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawCloseButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.CloseButton, state);
}
/// <summary>
/// Draws a window Close button control in the specified state
/// and bounds.
/// </summary>
/// <param name="style">The visual style file to use.</param>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
//// specifies the visual state of the button.</param>
public static void DrawCloseButton(VisualStyleFile style, Graphics g,
Rectangle bounds, WindowButtonState state)
{
DrawButton(style, g, bounds, WindowButtonType.CloseButton, state);
}
/// <summary>
/// Draws a window Help button control in the specified state and bounds.
/// </summary>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawHelpButton(Graphics g, Rectangle bounds,
WindowButtonState state)
{
DrawButton(g, bounds, WindowButtonType.HelpButton, state);
}
/// <summary>
/// Draws a window Help button control in the specified state and bounds.
/// </summary>
/// <param name="style">The visual style file to use.</param>
/// <param name="g">The Graphics used to draw the button.</param>
/// <param name="bounds">The button bounds.</param>
/// <param name="state">One of the WindowButtonState values that
/// specifies the visual state of the button.</param>
public static void DrawHelpButton(VisualStyleFile style, Graphics g,
Rectangle bounds, WindowButtonState state)
{
DrawButton(style, g, bounds, WindowButtonType.HelpButton, state);
}
/// <summary>
/// Draws a window Minize button control in the specified
/// state and bounds.
/// </summary>
/// <param name="g">The Graphics used t | ||||||||||||||||||||||||||||||||||||||||||||