// Requires Gdi\RECT.cs
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace Vanara.Interop
{
internal static partial class NativeMethods
{
private const string UXTHEME = "uxtheme.dll";
public class SafeThemeHandle : SafeHandle
{
public SafeThemeHandle(IntPtr hTheme, bool ownsHandle = true) : base(IntPtr.Zero, ownsHandle) { SetHandle(hTheme); }
protected override bool ReleaseHandle() => CloseThemeData(handle) == 0;
public override bool IsInvalid => handle == IntPtr.Zero;
public static implicit operator SafeThemeHandle(VisualStyleRenderer r) => new SafeThemeHandle(r.Handle, false);
}
[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)]
public delegate int DrawThemeTextCallback(SafeDCHandle hdc, string text, int textLen, ref RECT rc, int flags, IntPtr lParam);
[Flags]
public enum DrawThemeParentBackgroundFlags
{
None = 0,
/// If set, hdc is assumed to be a window DC, not a client DC.
/// DTPB_WINDOWDC
WindowDC = 1,
/// If set, this function sends a WM_CTLCOLORSTATIC message to the parent and uses the brush if one is provided. Otherwise, it uses COLOR_BTNFACE.
/// DTPB_USECTLCOLORSTATIC
UseCtlColorStaticMsg = 2,
/// If set, this function returns S_OK without sending a WM_CTLCOLORSTATIC message if the parent actually painted on WM_ERASEBKGND.
/// DTPB_USEERASEBKGND
UseEraseBkgndMsg = 4
}
public enum DrawThemeTextSystemFonts
{
Caption = 801,
SmallCaption = 802,
Menu = 803,
Status = 804,
MessageBox = 805,
IconTitle = 806
}
public enum IntegerListProperty
{
TransitionDuration = 6000
}
public enum OpenThemeDataOptions
{
None = 0,
/// Forces drawn images from this theme to stretch to fit the rectangles specified by drawing functions.
/// OTD_FORCE_RECT_SIZING
ForceRectSizing = 1,
/// Allows theme elements to be drawn in the non-client area of the window.
/// OTD_NONCLIENT
NonClient = 2
}
public enum ThemePropertyOrigin
{
/// Property was found in the state section.
/// PO_STATE
State = 0,
/// Property was found in the part section.
/// PO_PART
Part = 1,
/// Property was found in the class section.
/// PO_CLASS
Class = 2,
/// Property was found in the list of global variables.
/// PO_GLOBAL
Global = 3,
/// Property was not found.
/// PO_NOTFOUND
NotFound = 4
}
public enum TextShadowType
{
/// No shadow will be drawn.
/// TST_NONE
None = 0,
/// The shadow will be drawn to appear detailed underneath text.
/// TST_SINGLE
Single = 1,
/// The shadow will be drawn to appear blurred underneath text.
/// TST_CONTINUOUS
Continuous = 2
}
public enum ThemeSize
{
/// Receives the minimum size of a visual style part.
/// TS_MIN
Min,
/// Receives the size of the visual style part that will best fit the available space.
/// TS_TRUE
True,
/// Receives the size that the theme manager uses to draw a part.
/// TS_DRAW
Draw
}
[Flags]
public enum WindowThemeNonClientAttributes : int
{
/// Do Not Draw The Caption (Text)
NoDrawCaption = 0x00000001,
/// Do Not Draw the Icon
NoDrawIcon = 0x00000002,
/// Do Not Show the System Menu
NoSysMenu = 0x00000004,
/// Do Not Mirror the Question mark Symbol
NoMirrorHelp = 0x00000008
}
[Flags]
private enum DrawThemeTextOptionsMasks
{
TextColor = 1,
BorderColor = 2,
ShadowColor = 4,
ShadowType = 8,
ShadowOffset = 16,
BorderSize = 32,
FontProp = 64,
ColorProp = 128,
StateId = 256,
CalcRect = 512,
ApplyOverlay = 1024,
GlowSize = 2048,
Callback = 4096,
Composited = 8192
}
private enum WindowThemeAttributeType
{
NonClient = 1,
}
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int CloseThemeData(IntPtr hTheme);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int DrawThemeBackground(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, ref RECT pRect, PRECT pClipRect);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int DrawThemeBackgroundEx(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, ref RECT pRect, DrawThemeBackgroundOptions opts);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int DrawThemeIcon(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, ref RECT pRect, IntPtr himl, int iImageIndex);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int DrawThemeParentBackground(IntPtr hwnd, SafeDCHandle hdc, PRECT pRect);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int DrawThemeParentBackgroundEx(IntPtr hwnd, SafeDCHandle hdc, DrawThemeParentBackgroundFlags dwFlags, PRECT pRect);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int DrawThemeText(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, string text, int textLength, TextFormatFlags textFlags, int textFlags2, ref RECT pRect);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
[System.Security.SecurityCritical]
public static extern int DrawThemeTextEx(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, string text, int iCharCount, TextFormatFlags dwFlags, ref RECT pRect, ref DrawThemeTextOptions pOptions);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeBackgroundContentRect(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, ref RECT pBoundingRect, out RECT pContentRect);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeBitmap(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, int iPropId, int dwFlags, out IntPtr phBitmap);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeBool(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, [MarshalAs(UnmanagedType.Bool)] out bool pfVal);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeColor(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out int pColor);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeEnumValue(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out int piVal);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int GetThemeFilename(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, ref System.Text.StringBuilder pszBuff, int buffLength);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeInt(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out int piVal);
public static int[] GetThemeIntList(SafeThemeHandle hTheme, int partId, int stateId, int propId)
{
if (Environment.OSVersion.Version.Major < 6)
{
INTLIST_OLD l;
if (0 != GetThemeIntListPreVista(hTheme, partId, stateId, propId, out l))
return null;
var outlist = new int[l.iValueCount];
Array.Copy(l.iValues, outlist, l.iValueCount);
return outlist;
}
else
{
INTLIST l;
if (0 != GetThemeIntList(hTheme, partId, stateId, propId, out l))
return null;
var outlist = new int[l.iValueCount];
Array.Copy(l.iValues, outlist, l.iValueCount);
return outlist;
}
}
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int GetThemeMargins(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, int iPropId, IntPtr prc, out RECT pMargins);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeMetric(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, int iPropId, out int piVal);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemePartSize(SafeThemeHandle hTheme, SafeDCHandle hdc, int part, int state, PRECT pRect, ThemeSize eSize, out Size size);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemePosition(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out Point piVal);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemePropertyOrigin(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out ThemePropertyOrigin pOrigin);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeRect(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out RECT pRect);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeStream(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 5)] out byte[] pvStream, out int cbStream, IntPtr hInst);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int GetThemeString(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, ref System.Text.StringBuilder themeString, int themeStringLength);
[DllImport(UXTHEME, ExactSpelling = true)]
public static extern int GetThemeSysInt(SafeThemeHandle hTheme, int iIntID, out int piVal);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int GetThemeTextExtent(SafeThemeHandle hTheme, SafeDCHandle hdc, int iPartId, int iStateId, string text, int textLength, TextFormatFlags textFlags, ref RECT boundingRect, out RECT extentRect);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
public static extern int GetThemeTransitionDuration(SafeThemeHandle hTheme, int iPartId, int iStateIdFrom, int iStateIdTo, int iPropId, out int pdwDuration);
[DllImport(UXTHEME, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsThemeBackgroundPartiallyTransparent(SafeThemeHandle hTheme, int iPartId, int iStateId);
[DllImport(UXTHEME, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsThemePartDefined(SafeThemeHandle hTheme, int iPartId, int iStateId);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern IntPtr OpenThemeData(IntPtr hWnd, string classList);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern IntPtr OpenThemeDataEx(IntPtr hWnd, string classList, OpenThemeDataOptions dwFlags);
[DllImport(UXTHEME, ExactSpelling = true, CharSet = CharSet.Unicode)]
[System.Security.SecurityCritical]
public static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
public static int SetWindowThemeAttribute(IWin32Window wnd, WindowThemeNonClientAttributes ncAttrs, int ncAttrMasks = int.MaxValue)
{
var opt = new WTA_OPTIONS {Flags = ncAttrs, Mask = ncAttrMasks == int.MaxValue ? (int)ncAttrs : ncAttrMasks};
return SetWindowThemeAttribute(wnd?.Handle ?? IntPtr.Zero, WindowThemeAttributeType.NonClient, ref opt, Marshal.SizeOf(opt));
}
[DllImport(UXTHEME, ExactSpelling = true)]
private static extern int GetThemeIntList(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out INTLIST pIntList);
[DllImport(UXTHEME, ExactSpelling = true, EntryPoint = "GetThemeIntList")]
private static extern int GetThemeIntListPreVista(SafeThemeHandle hTheme, int iPartId, int iStateId, int iPropId, out INTLIST_OLD pIntList);
[DllImport(UXTHEME, ExactSpelling = true)]
[System.Security.SecurityCritical]
private static extern int SetWindowThemeAttribute(IntPtr hWnd, WindowThemeAttributeType wtype, ref WTA_OPTIONS attributes, int size);
///
/// Defines the options for the function.
///
[StructLayout(LayoutKind.Sequential)]
public struct DrawThemeTextOptions
{
private int dwSize;
private DrawThemeTextOptionsMasks dwMasks;
private int crText;
private int crBorder;
private int crShadow;
private TextShadowType iTextShadowType;
private Point ptShadowOffset;
private int iBorderSize;
private int iFontPropId;
private int iColorPropId;
private int iStateId;
[MarshalAs(UnmanagedType.Bool)]
private bool fApplyOverlay;
private int iGlowSize;
[MarshalAs(UnmanagedType.FunctionPtr)]
private DrawThemeTextCallback pfnDrawTextCallback;
private IntPtr lParam;
/// Initializes a new instance of the struct.
/// This value must be specified to initialize.
public DrawThemeTextOptions(bool init) : this()
{
dwSize = Marshal.SizeOf(typeof(DrawThemeTextOptions));
}
/// Gets or sets a value that specifies an alternate color property to use when drawing text.
/// The alternate color of the text.
public Color AlternateColor
{
get { return ColorTranslator.FromWin32(iColorPropId); }
set
{
iColorPropId = ColorTranslator.ToWin32(value);
dwMasks |= DrawThemeTextOptionsMasks.ColorProp;
}
}
/// Gets or sets an alternate font property to use when drawing text.
/// The alternate font.
public DrawThemeTextSystemFonts AlternateFont
{
get { return (DrawThemeTextSystemFonts)iFontPropId; }
set
{
iFontPropId = (int)value;
dwMasks |= DrawThemeTextOptionsMasks.FontProp;
}
}
///
/// Gets or sets a value indicating whether to draw text with antialiased alpha. Use of this flag requires a
/// top-down DIB section. This flag works only if the HDC passed to function DrawThemeTextEx has a top-down
/// DIB section currently selected in it. For more information, see Device-Independent Bitmaps.
///
/// true if antialiased alpha; otherwise, false.
public bool AntiAliasedAlpha
{
get { return (dwMasks & DrawThemeTextOptionsMasks.Composited) == DrawThemeTextOptionsMasks.Composited; }
set { SetFlag(DrawThemeTextOptionsMasks.Composited, value); }
}
///
/// Gets or sets a value indicating whether text will be drawn on top of the shadow and outline effects
/// (true) or if just the shadow and outline effects will be drawn (false).
///
/// true if drawn on top; otherwise, false.
public bool ApplyOverlay
{
get { return fApplyOverlay; }
set
{
fApplyOverlay = value;
dwMasks |= DrawThemeTextOptionsMasks.ApplyOverlay;
}
}
/// Gets or sets the color of the outline that will be drawn around the text.
/// The color of the border.
public Color BorderColor
{
get { return ColorTranslator.FromWin32(crBorder); }
set
{
crBorder = ColorTranslator.ToWin32(value);
dwMasks |= DrawThemeTextOptionsMasks.BorderColor;
}
}
/// Gets or sets the radius of the outline that will be drawn around the text.
/// The size of the border.
public int BorderSize
{
get { return iBorderSize; }
set
{
iBorderSize = value;
dwMasks |= DrawThemeTextOptionsMasks.BorderSize;
}
}
/// Gets or sets the callback function.
/// The callback function.
public DrawThemeTextCallback Callback
{
get { return pfnDrawTextCallback; }
set
{
pfnDrawTextCallback = value;
dwMasks |= DrawThemeTextOptionsMasks.Callback;
}
}
/// Gets or sets the size of a glow that will be drawn on the background prior to any text being drawn.
/// The size of the glow.
public int GlowSize
{
get { return iGlowSize; }
set
{
iGlowSize = value;
dwMasks |= DrawThemeTextOptionsMasks.GlowSize;
}
}
/// Gets or sets the parameter for callback back function specified by .
/// The parameter.
public IntPtr LParam
{
get { return lParam; }
set { lParam = value; }
}
///
/// Gets or sets a value indicating whether the pRect parameter of the function
/// that uses this structure will be used as both an in and an out parameter. After the function returns, the
/// pRect parameter will contain the rectangle that corresponds to the region calculated to be drawn.
///
/// true if returning the calculated rectangle; otherwise, false.
public bool ReturnCalculatedRectangle
{
get { return (dwMasks & DrawThemeTextOptionsMasks.CalcRect) == DrawThemeTextOptionsMasks.CalcRect; }
set { SetFlag(DrawThemeTextOptionsMasks.CalcRect, value); }
}
/// Gets or sets the color of the shadow drawn behind the text.
/// The color of the shadow.
public Color ShadowColor
{
get { return ColorTranslator.FromWin32(crShadow); }
set
{
crShadow = ColorTranslator.ToWin32(value);
dwMasks |= DrawThemeTextOptionsMasks.ShadowColor;
}
}
/// Gets or sets the amount of offset, in logical coordinates, between the shadow and the text.
/// The shadow offset.
public Point ShadowOffset
{
get { return new Point(ptShadowOffset.X, ptShadowOffset.Y); }
set
{
ptShadowOffset = value;
dwMasks |= DrawThemeTextOptionsMasks.ShadowOffset;
}
}
/// Gets or sets the type of the shadow that will be drawn behind the text.
/// The type of the shadow.
public TextShadowType ShadowType
{
get { return iTextShadowType; }
set
{
iTextShadowType = value;
dwMasks |= DrawThemeTextOptionsMasks.ShadowType;
}
}
/// Gets or sets the color of the text that will be drawn.
/// The color of the text.
public Color TextColor
{
get { return ColorTranslator.FromWin32(crText); }
set
{
crText = ColorTranslator.ToWin32(value);
dwMasks |= DrawThemeTextOptionsMasks.TextColor;
}
}
/// Gets an instance with default values set.
public static DrawThemeTextOptions Default => new DrawThemeTextOptions(true);
private void SetFlag(DrawThemeTextOptionsMasks f, bool value) { if (value) dwMasks |= f; else dwMasks &= ~f; }
}
///
/// The Options of What Attributes to Add/Remove
///
[StructLayout(LayoutKind.Sequential)]
private struct WTA_OPTIONS
{
public WindowThemeNonClientAttributes Flags;
public int Mask;
}
[StructLayout(LayoutKind.Sequential)]
private struct INTLIST
{
public int iValueCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 402)]
public int[] iValues;
}
[StructLayout(LayoutKind.Sequential)]
private struct INTLIST_OLD
{
public int iValueCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public int[] iValues;
}
///
/// Defines the options for the DrawThemeBackgroundEx function.
///
[StructLayout(LayoutKind.Sequential)]
public class DrawThemeBackgroundOptions
{
private int dwSize;
private DrawThemeBackgroundFlags dwFlags;
private RECT rcClip;
[Flags]
private enum DrawThemeBackgroundFlags
{
None = 0,
/// The ClipRectangle value is defined.
ClipRect = 1,
/// Deprecated. Draw transparent and alpha images as solid.
DrawSolid = 2,
/// Do not draw the border of the part (currently this value is only supported for bgtype=borderfill).
OmitBorder = 4,
/// Do not draw the content area of the part (currently this value is only supported for bgtype=borderfill).
OmitContent = 8,
/// Deprecated.
ComputingRegion = 16,
/// Assume the hdc is mirrored and flip images as appropriate (currently this value is only supported for bgtype=imagefile).
HasMirroredDC = 32,
/// Do not mirror the output; even in right-to-left (RTL) layout.
DoNotMirror = 64
}
///
/// Initializes a new instance of the class.
///
/// The rectangle to which drawing is clipped.
public DrawThemeBackgroundOptions(Rectangle? clipRect)
{
dwSize = Marshal.SizeOf(this);
ClipRectangle = clipRect;
}
/// Gets or sets the bounding rectangle of the clip region.
/// The clip rectangle.
public Rectangle? ClipRectangle
{
get
{
Rectangle r = rcClip;
return r.IsEmpty ? (Rectangle?)null : r;
}
set
{
rcClip = value ?? default(RECT);
SetFlag(DrawThemeBackgroundFlags.ClipRect, value.HasValue);
}
}
/// Gets or sets a value indicating whether omit drawing the border.
/// true if omit border; otherwise, false.
public bool OmitBorder { get { return GetFlag(DrawThemeBackgroundFlags.OmitBorder); } set { SetFlag(DrawThemeBackgroundFlags.OmitBorder, value); } }
/// Gets or sets a value indicating whether omit drawing the content area of the part.
/// true if omit content area of the part; otherwise, false.
public bool OmitContent { get { return GetFlag(DrawThemeBackgroundFlags.OmitContent); } set { SetFlag(DrawThemeBackgroundFlags.OmitContent, value); } }
/// Gets or sets a value indicating the hdc is mirrored and flip images as appropriate.
/// true if mirrored; otherwise, false.
public bool HasMirroredDC { get { return GetFlag(DrawThemeBackgroundFlags.HasMirroredDC); } set { SetFlag(DrawThemeBackgroundFlags.HasMirroredDC, value); } }
/// Gets or sets a value indicating whether to mirror the output; even in right-to-left (RTL) layout.
/// true if not mirroring; otherwise, false.
public bool DoNotMirror { get { return GetFlag(DrawThemeBackgroundFlags.DoNotMirror); } set { SetFlag(DrawThemeBackgroundFlags.DoNotMirror, value); } }
/// Performs an implicit conversion from to .
/// The clipping rectangle.
/// The result of the conversion.
public static implicit operator DrawThemeBackgroundOptions(Rectangle clipRectangle) => new DrawThemeBackgroundOptions(clipRectangle);
private bool GetFlag(DrawThemeBackgroundFlags f) => (dwFlags & f) == f;
private void SetFlag(DrawThemeBackgroundFlags f, bool value) { if (value) dwFlags |= f; else dwFlags &= ~f; }
}
}
}