Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / VisualStyles / VisualStyleRenderer.cs / 1 / VisualStyleRenderer.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA905:SystemAndMicrosoftNamespacesRequireApproval", Scope="namespace", Target="System.Windows.Forms.VisualStyles")] namespace System.Windows.Forms.VisualStyles { using System; using System.Drawing; using System.Windows.Forms.Internal; using System.Text; using System.Windows.Forms; using System.Collections; using System.ComponentModel; using System.Globalization; using System.Runtime.InteropServices; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.Win32; using System.Security; using System.Security.Permissions; ////// /// public sealed class VisualStyleRenderer { private const TextFormatFlags AllGraphicsProperties = TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.PreserveGraphicsTranslateTransform; internal const int EdgeAdjust = 0x2000; //used with Edges in VisualStyleRenderer.DrawThemeEdge private string _class; private int part; private int state; private int lastHResult = 0; private static int numberOfPossibleClasses = VisualStyleElement.Count; //used as size for themeHandles [ThreadStatic] private static Hashtable themeHandles = null; //per-thread cache of ThemeHandle objects. [ThreadStatic] private static long threadCacheVersion = 0; private static long globalCacheVersion = 0; static VisualStyleRenderer() { SystemEvents.UserPreferenceChanging += new UserPreferenceChangingEventHandler(OnUserPreferenceChanging); } ////// This class provides full feature parity with UxTheme API. /// ////// /// public static bool IsSupported { get { bool supported = (VisualStyleInformation.IsEnabledByUser && (Application.VisualStyleState == VisualStyleState.ClientAreaEnabled || Application.VisualStyleState == VisualStyleState.ClientAndNonClientAreasEnabled)); if (supported) { // VSWhidbey #171915: In some cases, this check isn't enough, since the theme handle creation // could fail for some other reason. Try creating a theme handle here - if successful, return true, // else return false. IntPtr hTheme = GetHandle("BUTTON", false); //Button is an arbitrary choice. supported = (hTheme != IntPtr.Zero); } return supported; } } ////// Returns true if visual styles are 1) supported by the OS 2) enabled in the client area /// and 3) currently applied to this application. Otherwise, it returns false. Note that /// if it returns false, attempting to instantiate/use objects of this class /// will result in exceptions being thrown. /// ////// /// public static bool IsElementDefined(VisualStyleElement element) { if (element == null) { throw new ArgumentNullException("element"); } return IsCombinationDefined(element.ClassName, element.Part); } private static bool IsCombinationDefined(string className, int part) { bool returnVal = false; if (!IsSupported) { if (!VisualStyleInformation.IsEnabledByUser) { throw new InvalidOperationException(SR.GetString(SR.VisualStyleNotActive)); } else { throw new InvalidOperationException(SR.GetString(SR.VisualStylesDisabledInClientArea)); } } if (className == null) { throw new ArgumentNullException("className"); } IntPtr hTheme = GetHandle(className, false); if (hTheme != IntPtr.Zero) { // IsThemePartDefined doesn't work for part = 0, although there are valid parts numbered 0. We // allow these explicitly here. if (part == 0) { returnVal = true; } else { returnVal = SafeNativeMethods.IsThemePartDefined(new HandleRef(null, hTheme), part, 0); } } //if the combo isn't defined, check the validity of our theme handle cache if (!returnVal) { using (ThemeHandle tHandle = ThemeHandle.Create(className, false)) { if (tHandle != null) { returnVal = SafeNativeMethods.IsThemePartDefined(new HandleRef(null, tHandle.NativeHandle), part, 0); } //if we did, in fact get a new correct theme handle, our cache is out of date -- update it now. if (returnVal) { RefreshCache(); } } } return returnVal; } ////// Returns true if the element is defined by the current visual style, else false. /// Note: /// 1) Throws an exception if IsSupported is false, since it is illegal to call it in that case. /// 2) The underlying API does not validate states. So if you pass in invalid state values, /// we might still return true. When you use an invalid state to render, you get the default /// state instead. /// ////// /// public VisualStyleRenderer(VisualStyleElement element) : this(element.ClassName, element.Part, element.State) { } ////// Constructor takes a VisualStyleElement. /// ////// /// public VisualStyleRenderer(string className, int part, int state) { if (!IsCombinationDefined(className, part)) { //internally this call takes care of IsSupported. throw new ArgumentException(SR.GetString(SR.VisualStylesInvalidCombination)); } this._class = className; this.part = part; this.state = state; } ////// Constructor takes weakly typed parameters - left for extensibility (using classes, parts or states /// not defined in the VisualStyleElement class.) /// ////// /// public string Class { get { return _class; } } ////// Returns the current _class. Use SetParameters to set. /// ////// /// public int Part { get { return part; } } ////// Returns the current part. Use SetParameters to set. /// ////// /// public int State { get { return state; } } ////// Returns the current state. Use SetParameters to set. /// ////// /// public IntPtr Handle { get { if (!IsSupported) { if (!VisualStyleInformation.IsEnabledByUser) { throw new InvalidOperationException(SR.GetString(SR.VisualStyleNotActive)); } else { throw new InvalidOperationException(SR.GetString(SR.VisualStylesDisabledInClientArea)); } } return GetHandle(_class); } } ////// Returns the underlying HTheme handle. /// NOTE: The handle gets invalidated when the theme changes or the user disables theming. When that /// happens, the user should requery this property to get the correct handle. To know when the /// theme changed, hook on to SystemEvents.UserPreferenceChanged and look for ThemeChanged /// category. /// ////// /// public void SetParameters(VisualStyleElement element) { if (element == null) { throw new ArgumentNullException("element"); } SetParameters(element.ClassName, element.Part, element.State); } ////// Used to set a new VisualStyleElement on this VisualStyleRenderer instance. /// ////// /// public void SetParameters(string className, int part, int state) { if (!IsCombinationDefined(className, part)) { //internally this call takes care of IsSupported. throw new ArgumentException(SR.GetString(SR.VisualStylesInvalidCombination)); } this._class = className; this.part = part; this.state = state; } ////// Used to set the _class, part and state that the VisualStyleRenderer object references. /// These parameters cannot be set individually. /// This method is present for extensibility. /// ////// /// public void DrawBackground(IDeviceContext dc, Rectangle bounds) { if (dc == null) { throw new ArgumentNullException("dc"); } if (bounds.Width < 0 || bounds.Height < 0) { return; } using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ){ HandleRef hdc = new HandleRef(wgr, wgr.WindowsGraphics.DeviceContext.Hdc); lastHResult = SafeNativeMethods.DrawThemeBackground( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), null ); } } ////// [See win32 equivalent.] /// ////// /// public void DrawBackground(IDeviceContext dc, Rectangle bounds, Rectangle clipRectangle) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (bounds.Width < 0 || bounds.Height < 0) { return; } if (clipRectangle.Width < 0 || clipRectangle.Height < 0) { return; } using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.DrawThemeBackground( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), new NativeMethods.COMRECT( clipRectangle ) ); } } ////// [See win32 equivalent.] /// ////// /// public Rectangle DrawEdge(IDeviceContext dc, Rectangle bounds, Edges edges, EdgeStyle style, EdgeEffects effects) { if (dc == null) { throw new ArgumentNullException("dc"); } if (!ClientUtils.IsEnumValid_Masked(edges, (int)edges,(UInt32)(Edges.Left | Edges.Top | Edges.Right | Edges.Bottom | Edges.Diagonal))) { throw new InvalidEnumArgumentException("edges", (int)edges, typeof(Edges)); } if (!ClientUtils.IsEnumValid_NotSequential(style, (int)style, (int)EdgeStyle.Raised,(int)EdgeStyle.Sunken,(int)EdgeStyle.Etched,(int)EdgeStyle.Bump )) { throw new InvalidEnumArgumentException("style", (int)style, typeof(EdgeStyle)); } if (!ClientUtils.IsEnumValid_Masked(effects, (int)effects, (UInt32)(EdgeEffects.FillInterior | EdgeEffects.Flat | EdgeEffects.Soft | EdgeEffects.Mono))) { throw new InvalidEnumArgumentException("effects", (int)effects, typeof(EdgeEffects)); } NativeMethods.COMRECT rect = new NativeMethods.COMRECT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.DrawThemeEdge( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), (int) style, (int) edges | (int) effects | EdgeAdjust, rect ); } return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom); } ////// [See win32 equivalent.] /// ////// /// public void DrawImage(Graphics g, Rectangle bounds, Image image) { if (g == null) { throw new ArgumentNullException("g"); } if (image == null) { throw new ArgumentNullException("image"); } if (bounds.Width < 0 || bounds.Height < 0) { return; } ImageList imageList = new ImageList(); try { imageList.Images.Add(image); } catch (Exception e) { if (ClientUtils.IsSecurityOrCriticalException(e)) { throw; } g.DrawImage(image, bounds); return; } DrawImage(g, bounds, imageList, 0); } ////// [See win32 equivalent.] /// This method uses Graphics.DrawImage as a backup if themed drawing does not work. /// ////// /// public void DrawImage(Graphics g, Rectangle bounds, ImageList imageList, int imageIndex) { if (g == null) { throw new ArgumentNullException("g"); } if (imageList == null) { throw new ArgumentNullException("imageList"); } if (imageIndex < 0 || imageIndex >= imageList.Images.Count) { throw new ArgumentOutOfRangeException("imageIndex", SR.GetString(SR.InvalidArgument, "imageIndex", imageIndex.ToString(CultureInfo.CurrentCulture))); } if (bounds.Width < 0 || bounds.Height < 0) { return; } // VSWhidbey #282742: DrawThemeIcon currently seems to do nothing, but still return S_OK. As a workaround, // we call DrawImage on the graphics object itself for now. A bug has been opened in Windows OS Bugs on this. //int returnVal = NativeMethods.S_FALSE; //using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { // HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); // returnVal = SafeNativeMethods.DrawThemeIcon( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), new HandleRef( this, imageList.Handle ), imageIndex ); //} //if (returnVal != NativeMethods.S_OK) { g.DrawImage(imageList.Images[imageIndex], bounds); //} } ////// [See win32 equivalent.] /// This method uses Graphics.DrawImage as a backup if themed drawing does not work. /// ////// /// public void DrawParentBackground(IDeviceContext dc, Rectangle bounds, Control childControl) { if (dc == null) { throw new ArgumentNullException("dc"); } if (childControl == null) { throw new ArgumentNullException("childControl"); } if (bounds.Width < 0 || bounds.Height < 0) { return; } if (childControl.Handle != IntPtr.Zero) { using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.DrawThemeParentBackground( new HandleRef( this, childControl.Handle ), hdc, new NativeMethods.COMRECT( bounds ) ); } } } ////// Given a graphics object and bounds to draw in, this method effectively asks the passed in /// control's parent to draw itself in there (it sends WM_ERASEBKGND & WM_PRINTCLIENT messages /// to the parent). /// ////// /// public void DrawText(IDeviceContext dc, Rectangle bounds, string textToDraw) { DrawText(dc, bounds, textToDraw, false); } ////// [See win32 equivalent.] /// ////// /// public void DrawText(IDeviceContext dc, Rectangle bounds, string textToDraw, bool drawDisabled) { DrawText(dc, bounds, textToDraw, drawDisabled, TextFormatFlags.HorizontalCenter); } ////// [See win32 equivalent.] /// ////// /// public void DrawText(IDeviceContext dc, Rectangle bounds, string textToDraw, bool drawDisabled, TextFormatFlags flags) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (bounds.Width < 0 || bounds.Height < 0) { return; } int disableFlag = drawDisabled?0x1:0; if (!String.IsNullOrEmpty(textToDraw)) { using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.DrawThemeText( new HandleRef( this, Handle ), hdc, part, state, textToDraw, textToDraw.Length, (int) flags, disableFlag, new NativeMethods.COMRECT( bounds ) ); } } } ////// [See win32 equivalent.] /// ////// /// public Rectangle GetBackgroundContentRectangle(IDeviceContext dc, Rectangle bounds) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (bounds.Width < 0 || bounds.Height < 0) { return Rectangle.Empty; } NativeMethods.COMRECT rect = new NativeMethods.COMRECT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeBackgroundContentRect( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), rect ); } return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom); } ////// [See win32 equivalent.] /// ////// /// public Rectangle GetBackgroundExtent(IDeviceContext dc, Rectangle contentBounds) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (contentBounds.Width < 0 || contentBounds.Height < 0) { return Rectangle.Empty; } NativeMethods.COMRECT rect = new NativeMethods.COMRECT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeBackgroundExtent( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( contentBounds ), rect ); } return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom); } ////// [See win32 equivalent.] /// ////// /// [SuppressUnmanagedCodeSecurity, SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] public Region GetBackgroundRegion(IDeviceContext dc, Rectangle bounds) { if (dc == null) { throw new ArgumentNullException("dc"); } if (bounds.Width < 0 || bounds.Height < 0) { return null; } IntPtr hRegion = IntPtr.Zero; using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeBackgroundRegion( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), ref hRegion ); } // GetThemeBackgroundRegion returns a null hRegion if it fails to create one, it could be because the bounding // box is too big. For more info see code in %xpsrc%\shell\themes\uxtheme\imagefile.cpp if you have an enlistment to it. return hRegion != IntPtr.Zero ? Region.FromHrgn(hRegion) : null; } ////// Computes the region for a regular or partially transparent background that is bounded by a specified /// rectangle. Return null if the region cannot be created. /// [See win32 equivalent.] /// ////// /// public bool GetBoolean(BooleanProperty prop) { if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)BooleanProperty.Transparent, (int)BooleanProperty.SourceShrink)){ throw new InvalidEnumArgumentException("prop", (int)prop, typeof(BooleanProperty)); } bool val = false; lastHResult = SafeNativeMethods.GetThemeBool(new HandleRef(this, Handle), part, state, (int)prop, ref val); return val; } ////// [See win32 equivalent.] /// ////// /// public Color GetColor(ColorProperty prop) { //valid values are 0xed9 to 0xeef if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)ColorProperty.BorderColor, (int)ColorProperty.AccentColorHint)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(ColorProperty)); } int color = 0; lastHResult = SafeNativeMethods.GetThemeColor(new HandleRef(this, Handle), part, state, (int)prop, ref color); return ColorTranslator.FromWin32(color); } ////// [See win32 equivalent.] /// ////// /// public int GetEnumValue(EnumProperty prop) { //valid values are 0xfa1 to 0xfaf if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)EnumProperty.BackgroundType, (int)EnumProperty.TrueSizeScalingType)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(EnumProperty)); } int val = 0; lastHResult = SafeNativeMethods.GetThemeEnumValue(new HandleRef(this, Handle), part, state, (int)prop, ref val); return val; } ////// [See win32 equivalent.] /// ////// /// public string GetFilename(FilenameProperty prop) { //valid values are 0xbb9 to 0xbc0 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)FilenameProperty.ImageFile, (int)FilenameProperty.GlyphImageFile)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(FilenameProperty)); } StringBuilder filename = new StringBuilder(512); lastHResult = SafeNativeMethods.GetThemeFilename(new HandleRef(this, Handle), part, state, (int)prop, filename, filename.Capacity); return filename.ToString(); } ////// [See win32 equivalent.] /// ////// /// [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] public Font GetFont(IDeviceContext dc, FontProperty prop) { if( dc == null ){ throw new ArgumentNullException("dc"); } //valid values are 0xa29 to 0xa29 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)FontProperty.GlyphFont, (int)FontProperty.GlyphFont)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(FontProperty)); } NativeMethods.LOGFONT logfont = new NativeMethods.LOGFONT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeFont( new HandleRef( this, Handle ), hdc, part, state, (int) prop, logfont ); } Font font = null; //check for a failed HR. if (NativeMethods.Succeeded(lastHResult)) { // SECREVIEW: Safe to assert here, since the logfont comes from a native api and not from the // caller of this method. The system creates the font handle. // IntSecurity.ObjectFromWin32Handle.Assert(); try { font = Font.FromLogFont(logfont); } catch (Exception e) { if (ClientUtils.IsSecurityOrCriticalException(e)) { throw; } //Looks like the font was not true type font = null; } } return font; } ////// [See win32 equivalent.] /// Returns null if the returned font was not true type, since GDI+ does not support it. /// ////// /// public int GetInteger(IntegerProperty prop) { //valid values are 0x961 to 0x978 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)IntegerProperty.ImageCount, (int)IntegerProperty.MinDpi5)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(IntegerProperty)); } int val = 0; lastHResult = SafeNativeMethods.GetThemeInt(new HandleRef(this, Handle), part, state, (int)prop, ref val); return val; } ////// [See win32 equivalent.] /// ////// /// public Size GetPartSize(IDeviceContext dc, ThemeSizeType type) { if( dc == null ){ throw new ArgumentNullException("dc"); } //valid values are 0x0 to 0x2 if (!ClientUtils.IsEnumValid(type, (int)type, (int)ThemeSizeType.Minimum, (int)ThemeSizeType.Draw)){ throw new InvalidEnumArgumentException("type", (int)type, typeof(ThemeSizeType)); } NativeMethods.SIZE size = new NativeMethods.SIZE(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemePartSize( new HandleRef( this, Handle ), hdc, part, state, null, type, size ); } return new Size(size.cx, size.cy); } ////// [See win32 equivalent.] /// ////// /// public Size GetPartSize(IDeviceContext dc, Rectangle bounds, ThemeSizeType type) { if( dc == null ){ throw new ArgumentNullException("dc"); } //valid values are 0x0 to 0x2 if (!ClientUtils.IsEnumValid(type, (int)type, (int)ThemeSizeType.Minimum, (int)ThemeSizeType.Draw)) { throw new InvalidEnumArgumentException("type", (int)type, typeof(ThemeSizeType)); } NativeMethods.SIZE size = new NativeMethods.SIZE(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemePartSize( new HandleRef( this, Handle ), hdc, part, state, new NativeMethods.COMRECT( bounds ), type, size ); } return new Size(size.cx, size.cy); } ////// [See win32 equivalent.] /// ////// /// public Point GetPoint(PointProperty prop) { //valid values are 0xd49 to 0xd50 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)PointProperty.Offset, (int)PointProperty.MinSize5)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(PointProperty)); } NativeMethods.POINT point = new NativeMethods.POINT(); lastHResult = SafeNativeMethods.GetThemePosition(new HandleRef(this, Handle), part, state, (int)prop, point); return new Point(point.x, point.y); } ////// [See win32 equivalent.] /// ////// /// public Padding GetMargins(IDeviceContext dc, MarginProperty prop) { if( dc == null ){ throw new ArgumentNullException("dc"); } //valid values are 0xe11 to 0xe13 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)MarginProperty.SizingMargins, (int)MarginProperty.CaptionMargins)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(MarginProperty)); } NativeMethods.MARGINS margins = new NativeMethods.MARGINS(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeMargins( new HandleRef( this, Handle ), hdc, part, state, (int) prop, ref margins ); } return new Padding(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); } ////// [See win32 equivalent.] /// ////// /// public string GetString(StringProperty prop) { //valid values are 0xc81 to 0xc81 if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)StringProperty.Text, (int)StringProperty.Text)) { throw new InvalidEnumArgumentException("prop", (int)prop, typeof(StringProperty)); } StringBuilder aString = new StringBuilder(512); lastHResult = SafeNativeMethods.GetThemeString(new HandleRef(this, Handle), part, state, (int)prop, aString, aString.Capacity); return aString.ToString(); } ////// [See win32 equivalent.] /// ////// /// public Rectangle GetTextExtent(IDeviceContext dc, string textToDraw, TextFormatFlags flags) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (String.IsNullOrEmpty(textToDraw)) { throw new ArgumentNullException("textToDraw"); } NativeMethods.COMRECT rect = new NativeMethods.COMRECT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeTextExtent( new HandleRef( this, Handle ), hdc, part, state, textToDraw, textToDraw.Length, (int) flags, null, rect ); } return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom); } ////// [See win32 equivalent.] /// ////// /// public Rectangle GetTextExtent(IDeviceContext dc, Rectangle bounds, string textToDraw, TextFormatFlags flags) { if( dc == null ){ throw new ArgumentNullException("dc"); } if (String.IsNullOrEmpty(textToDraw)) { throw new ArgumentNullException("textToDraw"); } NativeMethods.COMRECT rect = new NativeMethods.COMRECT(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeTextExtent( new HandleRef( this, Handle ), hdc, part, state, textToDraw, textToDraw.Length, (int) flags, new NativeMethods.COMRECT( bounds ), rect ); } return Rectangle.FromLTRB(rect.left, rect.top, rect.right, rect.bottom); } ////// [See win32 equivalent.] /// ////// /// public TextMetrics GetTextMetrics(IDeviceContext dc) { if( dc == null ){ throw new ArgumentNullException("dc"); } TextMetrics tm = new TextMetrics(); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.GetThemeTextMetrics( new HandleRef( this, Handle ), hdc, part, state, ref tm ); } return tm; } ////// [See win32 equivalent.] /// ////// /// // PM team has reviewed and decided on naming changes already [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public HitTestCode HitTestBackground(IDeviceContext dc, Rectangle backgroundRectangle, Point pt, HitTestOptions options) { if( dc == null ){ throw new ArgumentNullException("dc"); } int htCode = 0; NativeMethods.POINTSTRUCT point = new NativeMethods.POINTSTRUCT(pt.X, pt.Y); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.HitTestThemeBackground( new HandleRef( this, Handle ), hdc, part, state, (int) options, new NativeMethods.COMRECT( backgroundRectangle ), NativeMethods.NullHandleRef, point, ref htCode ); } return (HitTestCode)htCode; } ////// [See win32 equivalent.] /// ////// /// // PM team has reviewed and decided on naming changes already [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public HitTestCode HitTestBackground(Graphics g, Rectangle backgroundRectangle, Region region, Point pt, HitTestOptions options) { if (g == null) { throw new ArgumentNullException("g"); } IntPtr hRgn = region.GetHrgn(g); return HitTestBackground(g, backgroundRectangle, hRgn, pt, options); } ////// [See win32 equivalent.] /// ////// /// // PM team has reviewed and decided on naming changes already [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public HitTestCode HitTestBackground(IDeviceContext dc, Rectangle backgroundRectangle, IntPtr hRgn, Point pt, HitTestOptions options) { if( dc == null ){ throw new ArgumentNullException("dc"); } int htCode = 0; NativeMethods.POINTSTRUCT point = new NativeMethods.POINTSTRUCT(pt.X, pt.Y); using( WindowsGraphicsWrapper wgr = new WindowsGraphicsWrapper( dc, AllGraphicsProperties ) ) { HandleRef hdc = new HandleRef( wgr, wgr.WindowsGraphics.DeviceContext.Hdc ); lastHResult = SafeNativeMethods.HitTestThemeBackground( new HandleRef( this, Handle ), hdc, part, state, (int) options, new NativeMethods.COMRECT( backgroundRectangle ), new HandleRef( this, hRgn ), point, ref htCode ); } return (HitTestCode)htCode; } ////// [See win32 equivalent.] /// ////// /// public bool IsBackgroundPartiallyTransparent() { return (SafeNativeMethods.IsThemeBackgroundPartiallyTransparent(new HandleRef(this, Handle), part, state)); } ////// [See win32 equivalent.] /// ////// /// This is similar to GetLastError in Win32. It returns the last HRESULT returned from a native call /// into theme apis. We eat the errors and let the user handle any errors that occurred. /// public int LastHResult { get { return lastHResult; } } ////// /// private static void CreateThemeHandleHashtable() { themeHandles = new Hashtable(numberOfPossibleClasses); } ////// Instantiates the ThemeHandle cache hashtable. /// ////// /// private static void OnUserPreferenceChanging(object sender, UserPreferenceChangingEventArgs ea) { if (ea.Category == UserPreferenceCategory.VisualStyle) { // Let all threads know their cached handles are no longer valid; // cache refresh will happen at next handle access. // Note that if the theme changes 2^sizeof(long) times before a thread uses // its handle, this whole version hack won't work, but I don't see that happening. globalCacheVersion++; } } ////// Handles the ThemeChanged event. Basically, we need to ensure all per-thread theme handle /// caches are refreshed. /// ////// /// private static void RefreshCache() { ThemeHandle tHandle = null; if (themeHandles != null) { string[] classNames = new string[themeHandles.Keys.Count]; themeHandles.Keys.CopyTo(classNames, 0); // We don't call IsSupported here, since that could cause RefreshCache to be called again, // leading to stack overflow. bool isSupported = (VisualStyleInformation.IsEnabledByUser && (Application.VisualStyleState == VisualStyleState.ClientAreaEnabled || Application.VisualStyleState == VisualStyleState.ClientAndNonClientAreasEnabled)); foreach (string className in classNames) { tHandle = (ThemeHandle) themeHandles[className]; if (tHandle != null) { tHandle.Dispose(); } if (isSupported) { tHandle = ThemeHandle.Create(className, false); if (tHandle != null) { themeHandles[className] = tHandle; } } } } } private static IntPtr GetHandle(string className) { return GetHandle(className, true); } ////// Refreshes this thread's theme handle cache. /// ////// /// private static IntPtr GetHandle(string className, bool throwExceptionOnFail) { ThemeHandle tHandle; if (themeHandles == null) { CreateThemeHandleHashtable(); } if (threadCacheVersion != globalCacheVersion) { RefreshCache(); threadCacheVersion = globalCacheVersion; } if (!themeHandles.Contains(className)) { // see if it is already in cache tHandle = ThemeHandle.Create(className, throwExceptionOnFail); if (tHandle == null) { return IntPtr.Zero; } themeHandles.Add(className, tHandle); } else { tHandle = (ThemeHandle) themeHandles[className]; } return tHandle.NativeHandle; } // This wrapper class is needed for safely cleaning up TLS cache of handles. private class ThemeHandle : IDisposable { private IntPtr _hTheme = IntPtr.Zero; private ThemeHandle(IntPtr hTheme) { _hTheme = hTheme; } public IntPtr NativeHandle { get { return _hTheme; } } public static ThemeHandle Create(string className, bool throwExceptionOnFail) { // HThemes don't require an HWND, so just use a null one IntPtr hTheme = IntPtr.Zero; try { hTheme = SafeNativeMethods.OpenThemeData(new HandleRef(null, IntPtr.Zero), className); } catch (Exception e) { //We don't want to eat critical exceptions if (ClientUtils.IsSecurityOrCriticalException(e)) { throw; } if (throwExceptionOnFail) { throw new InvalidOperationException(SR.GetString(SR.VisualStyleHandleCreationFailed), e); } else { return null; } } if (hTheme == IntPtr.Zero) { if (throwExceptionOnFail) { throw new InvalidOperationException(SR.GetString(SR.VisualStyleHandleCreationFailed)); } else { return null; } } return new ThemeHandle(hTheme); } public void Dispose() { if (_hTheme != IntPtr.Zero) { SafeNativeMethods.CloseThemeData(new HandleRef(null, _hTheme)); _hTheme = IntPtr.Zero; } GC.SuppressFinalize(this); } ~ThemeHandle() { Dispose(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved./// Retrieves a IntPtr theme handle for the given class from the themeHandle cache. If its not /// present in the cache, it creates a new ThemeHandle object and stores it there. /// ///
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DispatcherExceptionEventArgs.cs
- AvtEvent.cs
- SchemaImporterExtensionsSection.cs
- TypeUsageBuilder.cs
- LowerCaseStringConverter.cs
- ArraySortHelper.cs
- FormattedText.cs
- PackageDigitalSignatureManager.cs
- DbConnectionPoolGroupProviderInfo.cs
- FileRecordSequenceCompletedAsyncResult.cs
- WindowsListViewGroup.cs
- RowCache.cs
- Profiler.cs
- BStrWrapper.cs
- CqlWriter.cs
- OnOperation.cs
- FormView.cs
- ScrollChrome.cs
- SmtpSection.cs
- CanonicalFontFamilyReference.cs
- AppSecurityManager.cs
- TemplateBindingExtensionConverter.cs
- ObjectQuery_EntitySqlExtensions.cs
- CustomExpression.cs
- XmlStringTable.cs
- ImageListStreamer.cs
- ListCollectionView.cs
- AnchoredBlock.cs
- FormattedText.cs
- GridViewCellAutomationPeer.cs
- AudioDeviceOut.cs
- XamlSerializer.cs
- XpsFilter.cs
- Constants.cs
- ProfessionalColors.cs
- ExecutionEngineException.cs
- TextCollapsingProperties.cs
- Rect.cs
- _HTTPDateParse.cs
- TriState.cs
- IntSecurity.cs
- ExtensibleClassFactory.cs
- ColumnCollection.cs
- Sequence.cs
- TypeUtil.cs
- ExpandCollapsePattern.cs
- TogglePatternIdentifiers.cs
- AsyncCompletedEventArgs.cs
- Expression.DebuggerProxy.cs
- Stack.cs
- AggregateNode.cs
- _OverlappedAsyncResult.cs
- MappingItemCollection.cs
- ObjectSet.cs
- ProviderBase.cs
- CommandEventArgs.cs
- OpenTypeCommon.cs
- FormViewCommandEventArgs.cs
- UrlMapping.cs
- XmlRawWriterWrapper.cs
- SegmentInfo.cs
- AdapterDictionary.cs
- HttpResponseHeader.cs
- SqlUserDefinedTypeAttribute.cs
- DisplayNameAttribute.cs
- NavigationEventArgs.cs
- XmlSchemaDatatype.cs
- ApplicationException.cs
- CommandSet.cs
- SortQuery.cs
- ButtonStandardAdapter.cs
- EntityDesignerUtils.cs
- DocumentPageHost.cs
- ValidationErrorInfo.cs
- CharacterString.cs
- HttpCacheVary.cs
- ContractMethodParameterInfo.cs
- SafeNativeMethods.cs
- ErrorHandlerFaultInfo.cs
- SystemIcmpV4Statistics.cs
- _TransmitFileOverlappedAsyncResult.cs
- VectorAnimationBase.cs
- Calendar.cs
- MergeLocalizationDirectives.cs
- BatchServiceHost.cs
- TrackBarDesigner.cs
- userdatakeys.cs
- ConsoleKeyInfo.cs
- AutoGeneratedField.cs
- IItemProperties.cs
- FindRequestContext.cs
- CodeTypeMemberCollection.cs
- WebHttpBehavior.cs
- RSAProtectedConfigurationProvider.cs
- FormatException.cs
- Utils.cs
- TypefaceCollection.cs
- OperationAbortedException.cs
- ToolStripGrip.cs
- HttpServerVarsCollection.cs