//#########################################################################################
//★★★★★★★ http://www.cnpopsoft.com [华普软件] ★★★★★★★
//★★★★★★★ 华普软件 - VB & C#.NET 专业论文与源码荟萃! ★★★★★★★
//#########################################################################################
/*
* Copyright ?2005, Mathew Hall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
using System;
using System.Drawing;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using XPTable.Win32;
namespace XPTable.Themes
{
///
/// A class that contains methods for drawing Windows XP themed Control parts
///
public abstract class ThemeManager
{
#region Constructor
///
/// Initializes a new instance of the ThemeManager class with default settings
///
protected ThemeManager()
{
}
#endregion
#region Methods
#region Painting
#region Button
///
/// Draws a push button in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the button
/// A PushButtonStates value that specifies the
/// state to draw the button in
public static void DrawButton(Graphics g, Rectangle buttonRect, PushButtonStates state)
{
ThemeManager.DrawButton(g, buttonRect, buttonRect, state);
}
///
/// Draws a push button in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the button
/// The Rectangle that represents the clipping area
/// A PushButtonStates value that specifies the
/// state to draw the button in
public static void DrawButton(Graphics g, Rectangle buttonRect, Rectangle clipRect, PushButtonStates state)
{
if (g == null || buttonRect.Width <= 0 || buttonRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.Button, (int) ButtonParts.PushButton, (int) state, buttonRect, clipRect);
}
else
{
ControlPaint.DrawButton(g, buttonRect, ThemeManager.ConvertPushButtonStateToButtonState(state));
}
}
///
/// Converts the specified PushButtonStates value to a ButtonState value
///
/// The PushButtonStates value to be converted
/// A ButtonState value that represents the specified PushButtonStates
/// value
private static ButtonState ConvertPushButtonStateToButtonState(PushButtonStates state)
{
switch (state)
{
case PushButtonStates.Pressed:
{
return ButtonState.Pushed;
}
case PushButtonStates.Disabled:
{
return ButtonState.Inactive;
}
}
return ButtonState.Normal;
}
#endregion
#region CheckBox
///
/// Draws a check box in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the check box
/// A CheckBoxStates value that specifies the
/// state to draw the check box in
public static void DrawCheck(Graphics g, Rectangle checkRect, CheckBoxStates state)
{
ThemeManager.DrawCheck(g, checkRect, checkRect, state);
}
///
/// Draws a check box in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the check box
/// The Rectangle that represents the clipping area
/// A CheckBoxStates value that specifies the
/// state to draw the check box in
public static void DrawCheck(Graphics g, Rectangle checkRect, Rectangle clipRect, CheckBoxStates state)
{
if (g == null || checkRect.Width <= 0 || checkRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.Button, (int) ButtonParts.CheckBox, (int) state, checkRect, clipRect);
}
else
{
if (IsMixed(state))
{
ControlPaint.DrawMixedCheckBox(g, checkRect, ThemeManager.ConvertCheckBoxStateToButtonState(state));
}
else
{
ControlPaint.DrawCheckBox(g, checkRect, ThemeManager.ConvertCheckBoxStateToButtonState(state));
}
}
}
///
/// Converts the specified CheckBoxStates value to a ButtonState value
///
/// The CheckBoxStates value to be converted
/// A ButtonState value that represents the specified CheckBoxStates
/// value
private static ButtonState ConvertCheckBoxStateToButtonState(CheckBoxStates state)
{
switch (state)
{
case CheckBoxStates.UncheckedPressed:
{
return ButtonState.Pushed;
}
case CheckBoxStates.UncheckedDisabled:
{
return ButtonState.Inactive;
}
case CheckBoxStates.CheckedNormal:
case CheckBoxStates.CheckedHot:
{
return ButtonState.Checked;
}
case CheckBoxStates.CheckedPressed:
{
return (ButtonState.Checked | ButtonState.Pushed);
}
case CheckBoxStates.CheckedDisabled:
{
return (ButtonState.Checked | ButtonState.Inactive);
}
case CheckBoxStates.MixedNormal:
case CheckBoxStates.MixedHot:
{
return ButtonState.Checked;
}
case CheckBoxStates.MixedPressed:
{
return (ButtonState.Checked | ButtonState.Pushed);
}
case CheckBoxStates.MixedDisabled:
{
return (ButtonState.Checked | ButtonState.Inactive);
}
}
return ButtonState.Normal;
}
///
/// Returns whether the specified CheckBoxStates value is in an
/// indeterminate state
///
/// The CheckBoxStates value to be checked
/// true if the specified CheckBoxStates value is in an
/// indeterminate state, false otherwise
private static bool IsMixed(CheckBoxStates state)
{
switch (state)
{
case CheckBoxStates.MixedNormal:
case CheckBoxStates.MixedHot:
case CheckBoxStates.MixedPressed:
case CheckBoxStates.MixedDisabled:
{
return true;
}
}
return false;
}
#endregion
#region ColumnHeader
///
/// Draws a column header in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the column header
/// A ColumnHeaderStates value that specifies the
/// state to draw the column header in
public static void DrawColumnHeader(Graphics g, Rectangle headerRect, ColumnHeaderStates state)
{
ThemeManager.DrawColumnHeader(g, headerRect, headerRect, state);
}
///
/// Draws a column header in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the column header
/// The Rectangle that represents the clipping area
/// A ColumnHeaderStates value that specifies the
/// state to draw the column header in
public static void DrawColumnHeader(Graphics g, Rectangle headerRect, Rectangle clipRect, ColumnHeaderStates state)
{
if (g == null || headerRect.Width <= 0 || headerRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.ColumnHeader, (int) ColumnHeaderParts.HeaderItem, (int) state, headerRect, clipRect);
}
else
{
g.FillRectangle(SystemBrushes.Control, headerRect);
if (state == ColumnHeaderStates.Pressed)
{
g.DrawRectangle(SystemPens.ControlDark, headerRect.X, headerRect.Y, headerRect.Width-1, headerRect.Height-1);
}
else
{
ControlPaint.DrawBorder3D(g, headerRect.X, headerRect.Y, headerRect.Width, headerRect.Height, Border3DStyle.RaisedInner);
}
}
}
#endregion
#region ComboBoxButton
///
/// Draws a combobox button in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the combobox button
/// A ComboBoxStates value that specifies the
/// state to draw the combobox button in
public static void DrawComboBoxButton(Graphics g, Rectangle buttonRect, ComboBoxStates state)
{
ThemeManager.DrawComboBoxButton(g, buttonRect, buttonRect, state);
}
///
/// Draws a combobox button in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the button
/// The Rectangle that represents the clipping area
/// A ComboBoxStates value that specifies the
/// state to draw the combobox button in
public static void DrawComboBoxButton(Graphics g, Rectangle buttonRect, Rectangle clipRect, ComboBoxStates state)
{
if (g == null || buttonRect.Width <= 0 || buttonRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.ComboBox, (int) ComboBoxParts.DropDownButton, (int) state, buttonRect, clipRect);
}
else
{
ControlPaint.DrawComboButton(g, buttonRect, ThemeManager.ConvertComboBoxStateToButtonState(state));
}
}
///
/// Converts the specified ComboBoxStates value to a ButtonState value
///
/// The ComboBoxStates value to be converted
/// A ButtonState value that represents the specified ComboBoxStates
/// value
private static ButtonState ConvertComboBoxStateToButtonState(ComboBoxStates state)
{
switch (state)
{
case ComboBoxStates.Pressed:
{
return ButtonState.Pushed;
}
case ComboBoxStates.Disabled:
{
return ButtonState.Inactive;
}
}
return ButtonState.Normal;
}
#endregion
#region ProgressBar
///
/// Draws a ProgressBar on the specified graphics surface, and within
/// the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the ProgressBar
public static void DrawProgressBar(Graphics g, Rectangle drawRect)
{
ThemeManager.DrawProgressBar(g, drawRect, drawRect);
}
///
/// Draws a ProgressBar on the specified graphics surface, and within
/// the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the ProgressBar
/// The Rectangle that represents the clipping area
public static void DrawProgressBar(Graphics g, Rectangle drawRect, Rectangle clipRect)
{
if (g == null || drawRect.Width <= 0 || drawRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.ProgressBar, (int) ProgressBarParts.Bar, 0, drawRect, clipRect);
}
else
{
// background
g.FillRectangle(Brushes.White, drawRect);
// 3d border
//ControlPaint.DrawBorder3D(g, drawRect, Border3DStyle.SunkenInner);
// flat border
g.DrawRectangle(SystemPens.ControlDark, drawRect.Left, drawRect.Top, drawRect.Width-1, drawRect.Height-1);
}
}
///
/// Draws the ProgressBar's chunks on the specified graphics surface, and within
/// the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the ProgressBar
public static void DrawProgressBarChunks(Graphics g, Rectangle drawRect)
{
ThemeManager.DrawProgressBarChunks(g, drawRect, drawRect);
}
///
/// Draws the ProgressBar's chunks on the specified graphics surface, and within
/// the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the ProgressBar
/// The Rectangle that represents the clipping area
public static void DrawProgressBarChunks(Graphics g, Rectangle drawRect, Rectangle clipRect)
{
if (g == null || drawRect.Width <= 0 || drawRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.ProgressBar, (int) ProgressBarParts.Chunk, 0, drawRect, clipRect);
}
else
{
g.FillRectangle(SystemBrushes.Highlight, drawRect);
}
}
#endregion
#region RadioButton
///
/// Draws a RadioButton in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the RadioButton
/// A RadioButtonStates value that specifies the
/// state to draw the RadioButton in
public static void DrawRadioButton(Graphics g, Rectangle checkRect, RadioButtonStates state)
{
ThemeManager.DrawRadioButton(g, checkRect, checkRect, state);
}
///
/// Draws a RadioButton in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the RadioButton
/// The Rectangle that represents the clipping area
/// A RadioButtonStates value that specifies the
/// state to draw the RadioButton in
public static void DrawRadioButton(Graphics g, Rectangle checkRect, Rectangle clipRect, RadioButtonStates state)
{
if (g == null || checkRect.Width <= 0 || checkRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.Button, (int) ButtonParts.RadioButton, (int) state, checkRect, clipRect);
}
else
{
ControlPaint.DrawRadioButton(g, checkRect, ThemeManager.ConvertRadioButtonStateToButtonState(state));
}
}
///
/// Converts the specified RadioButtonStates value to a ButtonState value
///
/// The RadioButtonStates value to be converted
/// A ButtonState value that represents the specified RadioButtonStates
/// value
private static ButtonState ConvertRadioButtonStateToButtonState(RadioButtonStates state)
{
switch (state)
{
case RadioButtonStates.UncheckedPressed:
{
return ButtonState.Pushed;
}
case RadioButtonStates.UncheckedDisabled:
{
return ButtonState.Inactive;
}
case RadioButtonStates.CheckedNormal:
case RadioButtonStates.CheckedHot:
{
return ButtonState.Checked;
}
case RadioButtonStates.CheckedPressed:
{
return (ButtonState.Checked | ButtonState.Pushed);
}
case RadioButtonStates.CheckedDisabled:
{
return (ButtonState.Checked | ButtonState.Inactive);
}
}
return ButtonState.Normal;
}
#endregion
#region TabPage
///
/// Draws a TabPage body on the specified graphics surface, and within the
/// specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the TabPage body
internal static void DrawTabPageBody(Graphics g, Rectangle tabRect)
{
ThemeManager.DrawTabPageBody(g, tabRect, tabRect);
}
///
/// Draws a TabPage body on the specified graphics surface, and within the
/// specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the TabPage body
/// The Rectangle that represents the clipping area
internal static void DrawTabPageBody(Graphics g, Rectangle tabRect, Rectangle clipRect)
{
if (g == null || tabRect.Width <= 0 || tabRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.TabControl, (int) TabParts.Body, 0, tabRect, clipRect);
}
else
{
g.FillRectangle(SystemBrushes.Control, Rectangle.Intersect(clipRect, tabRect));
}
}
#endregion
#region TextBox
///
/// Draws a TextBox in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the TextBox
/// A TextBoxStates value that specifies the
/// state to draw the TextBox in
public static void DrawTextBox(Graphics g, Rectangle textRect, TextBoxStates state)
{
ThemeManager.DrawTextBox(g, textRect, textRect, state);
}
///
/// Draws a TextBox in the specified state, on the specified graphics
/// surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the TextBox
/// The Rectangle that represents the clipping area
/// A TextBoxStates value that specifies the
/// state to draw the TextBox in
public static void DrawTextBox(Graphics g, Rectangle textRect, Rectangle clipRect, TextBoxStates state)
{
if (g == null || textRect.Width <= 0 || textRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.TextBox, (int) TextBoxParts.EditText, (int) state, textRect, clipRect);
}
else
{
ControlPaint.DrawBorder3D(g, textRect, Border3DStyle.Sunken);
}
}
#endregion
#region UpDown
///
/// Draws an UpDown's up and down buttons in the specified state, on the specified
/// graphics surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the up button
/// An UpDownStates value that specifies the
/// state to draw the up button in
/// The Rectangle that represents the dimensions
/// of the down button
/// An UpDownStates value that specifies the
/// state to draw the down button in
public static void DrawUpDownButtons(Graphics g, Rectangle upButtonRect, UpDownStates upButtonState, Rectangle downButtonRect, UpDownStates downButtonState)
{
ThemeManager.DrawUpDownButtons(g, upButtonRect, upButtonRect, upButtonState, downButtonRect, downButtonRect, downButtonState);
}
///
/// Draws an UpDown's up and down buttons in the specified state, on the specified
/// graphics surface, and within the specified bounds
///
/// The Graphics to draw on
/// The Rectangle that represents the dimensions
/// of the up button
/// The Rectangle that represents the clipping area
/// for the up button
/// An UpDownStates value that specifies the
/// state to draw the up button in
/// The Rectangle that represents the dimensions
/// of the down button
/// The Rectangle that represents the clipping area
/// for the down button
/// An UpDownStates value that specifies the
/// state to draw the down button in
public static void DrawUpDownButtons(Graphics g, Rectangle upButtonRect, Rectangle upButtonClipRect, UpDownStates upButtonState, Rectangle downButtonRect, Rectangle downButtonClipRect, UpDownStates downButtonState)
{
if (g == null)
{
return;
}
if (upButtonRect.Width > 0 && upButtonRect.Height > 0 && upButtonClipRect.Width > 0 && upButtonClipRect.Height > 0)
{
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.UpDown, (int) UpDownParts.Up, (int) upButtonState, upButtonRect, upButtonClipRect);
}
else
{
ControlPaint.DrawScrollButton(g, upButtonRect, ScrollButton.Up, ThemeManager.ConvertUpDownStateToButtonState(upButtonState));
}
}
if (downButtonRect.Width > 0 && downButtonRect.Height > 0 && downButtonClipRect.Width > 0 && downButtonClipRect.Height > 0)
{
if (ThemeManager.VisualStylesEnabled)
{
ThemeManager.DrawThemeBackground(g, ThemeClasses.UpDown, (int) UpDownParts.Down, (int) downButtonState, downButtonRect, downButtonClipRect);
}
else
{
ControlPaint.DrawScrollButton(g, downButtonRect, ScrollButton.Down, ThemeManager.ConvertUpDownStateToButtonState(downButtonState));
}
}
}
///
/// Converts the specified UpDownStates value to a ButtonState value
///
/// The UpDownStates value to be converted
/// A ButtonState value that represents the specified UpDownStates
/// value
private static ButtonState ConvertUpDownStateToButtonState(UpDownStates state)
{
switch (state)
{
case UpDownStates.Pressed:
{
return ButtonState.Pushed;
}
case UpDownStates.Disabled:
{
return ButtonState.Inactive;
}
}
return ButtonState.Normal;
}
#endregion
#region Theme Background
///
/// Draws the background image defined by the visual style for the specified control part
///
/// The Graphics to draw on
/// The class of the part to draw
/// The part to draw
/// The state of the part to draw
/// The Rectangle in which the part is drawn
public static void DrawThemeBackground(Graphics g, string windowClass, int part, int partState, Rectangle drawRect)
{
//
ThemeManager.DrawThemeBackground(g, windowClass, part, partState, drawRect, drawRect);
}
///
/// Draws the background image defined by the visual style for the specified control part
///
/// The Graphics to draw on
/// The class of the part to draw
/// The part to draw
/// The state of the part to draw
/// The Rectangle in which the part is drawn
/// The Rectangle that represents the clipping area for the part
public static void DrawThemeBackground(Graphics g, string windowClass, int part, int partState, Rectangle drawRect, Rectangle clipRect)
{
if (g == null || drawRect.Width <= 0 || drawRect.Height <= 0 || clipRect.Width <= 0 || clipRect.Height <= 0)
{
return;
}
// open theme data
IntPtr hTheme = IntPtr.Zero;
hTheme = NativeMethods.OpenThemeData(hTheme, windowClass);
// make sure we have a valid handle
if (hTheme != IntPtr.Zero)
{
// get a graphics object the UxTheme can draw into
IntPtr hdc = g.GetHdc();
// get the draw and clipping rectangles
RECT dRect = RECT.FromRectangle(drawRect);
RECT cRect = RECT.FromRectangle(clipRect);
// draw the themed background
NativeMethods.DrawThemeBackground(hTheme, hdc, part, partState, ref dRect, ref cRect);
// clean up resources
g.ReleaseHdc(hdc);
}
// close the theme handle
NativeMethods.CloseThemeData(hTheme);
}
#endregion
#endregion
#endregion
#region Properties
///
/// Gets whether Visual Styles are supported by the system
///
public static bool VisualStylesSupported
{
get
{
return OSFeature.Feature.IsPresent(OSFeature.Themes);
}
}
///
/// Gets whether Visual Styles are enabled for the application
///
public static bool VisualStylesEnabled
{
get
{
if (VisualStylesSupported)
{
// are themes enabled
if (NativeMethods.IsThemeActive() && NativeMethods.IsAppThemed())
{
return GetComctlVersion().Major >= 6;
}
}
return false;
}
}
///
/// Returns a Version object that contains information about the verion
/// of the CommonControls that the application is using
///
/// A Version object that contains information about the verion
/// of the CommonControls that the application is using
private static Version GetComctlVersion()
{
DLLVERSIONINFO comctlVersion = new DLLVERSIONINFO();
comctlVersion.cbSize = Marshal.SizeOf(typeof(DLLVERSIONINFO));
if (NativeMethods.DllGetVersion(ref comctlVersion) == 0)
{
return new Version(comctlVersion.dwMajorVersion, comctlVersion.dwMinorVersion, comctlVersion.dwBuildNumber);
}
return new Version();
}
#endregion
}
}