// 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; } } } }