VisualStyleRenderer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / 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;
 
    /// 
    ///  
    ///     
    ///       This class provides full feature parity with UxTheme API.
    ///     
    /// 
    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);
        }
 

        ///  
        ///  
        ///    
        ///       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 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 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 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; 
        }
 
        /// 
        /// 
        ///    
        ///       Constructor takes a VisualStyleElement. 
        ///    
        ///  
        public VisualStyleRenderer(VisualStyleElement element) : this(element.ClassName, element.Part, element.State) { 
        }
 
        /// 
        /// 
        ///    
        ///       Constructor takes weakly typed parameters - left for extensibility (using classes, parts or states 
        ///       not defined in the VisualStyleElement class.)
        ///     
        ///  
        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; 
        } 

        ///  
        /// 
        ///    
        ///       Returns the current _class. Use SetParameters to set.
        ///     
        /// 
        public string Class { 
            get { 
                return _class;
            } 
        }

        /// 
        ///  
        ///    
        ///       Returns the current part. Use SetParameters to set. 
        ///     
        /// 
        public int Part { 
            get {
                return part;
            }
        } 

        ///  
        ///  
        ///    
        ///       Returns the current state. Use SetParameters to set. 
        ///    
        /// 
        public int State {
            get { 
                return state;
            } 
        } 

        ///  
        /// 
        ///    
        ///       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 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);
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Used to set a new VisualStyleElement on this VisualStyleRenderer instance.
        ///    
        /// 
        public void SetParameters(VisualStyleElement element) { 
            if (element == null) {
                throw new ArgumentNullException("element"); 
            } 

            SetParameters(element.ClassName, element.Part, element.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 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; 
        }

        /// 
        ///  
        ///    
        ///       [See win32 equivalent.] 
        ///     
        /// 
        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.]
        ///       This method uses Graphics.DrawImage as a backup if themed drawing does not work.
        ///    
        ///  
        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);
            //} 
        } 

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

        /// 
        /// 
        ///     
        ///       [See win32 equivalent.]
        ///     
        ///  
        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);
        }
 
        /// 
        ///  
        ///     
        ///       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.]
        ///    
        /// 
        [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. 

 		if (hRegion == IntPtr.Zero) { 
			return null; 
		}
 
		// From the GDI+ sources it doesn't appear as if they take ownership of the hRegion, so this is safe to do.
 		// We need to DeleteObject in order to not leak. DevDiv Bugs 169791
		Region region = Region.FromHrgn(hRegion);
 		SafeNativeMethods.ExternalDeleteObject(new HandleRef(null, hRegion)); 
 		return region;
 
        } 

        ///  
        /// 
        ///    
        ///       [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.]
        ///       Returns null if the returned font was not true type, since GDI+ does not support it.
        ///    
        ///  
        [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.] 
        ///    
        /// 
        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)); 
        }
 
        /// 
        /// 
        ///  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;
            } 
        }

        /// 
        ///  
        ///    
        ///       Instantiates the ThemeHandle cache hashtable. 
        ///     
        /// 
        private static void CreateThemeHandleHashtable() { 
            themeHandles = new Hashtable(numberOfPossibleClasses);
        }

        ///  
        /// 
        ///     
        ///       Handles the ThemeChanged event. Basically, we need to ensure all per-thread theme handle 
        ///       caches are refreshed.
        ///     
        /// 
        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++;
            } 
        }

        /// 
        ///  
        ///    
        ///     Refreshes this thread's theme handle cache. 
        ///     
        /// 
        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);
        } 

        ///  
        ///  
        ///    
        ///     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.
        ///    
        /// 
        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.
// 
//----------------------------------------------------------------------------- 
[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;
 
    /// 
    ///  
    ///     
    ///       This class provides full feature parity with UxTheme API.
    ///     
    /// 
    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);
        }
 

        ///  
        ///  
        ///    
        ///       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 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 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 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; 
        }
 
        /// 
        /// 
        ///    
        ///       Constructor takes a VisualStyleElement. 
        ///    
        ///  
        public VisualStyleRenderer(VisualStyleElement element) : this(element.ClassName, element.Part, element.State) { 
        }
 
        /// 
        /// 
        ///    
        ///       Constructor takes weakly typed parameters - left for extensibility (using classes, parts or states 
        ///       not defined in the VisualStyleElement class.)
        ///     
        ///  
        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; 
        } 

        ///  
        /// 
        ///    
        ///       Returns the current _class. Use SetParameters to set.
        ///     
        /// 
        public string Class { 
            get { 
                return _class;
            } 
        }

        /// 
        ///  
        ///    
        ///       Returns the current part. Use SetParameters to set. 
        ///     
        /// 
        public int Part { 
            get {
                return part;
            }
        } 

        ///  
        ///  
        ///    
        ///       Returns the current state. Use SetParameters to set. 
        ///    
        /// 
        public int State {
            get { 
                return state;
            } 
        } 

        ///  
        /// 
        ///    
        ///       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 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);
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Used to set a new VisualStyleElement on this VisualStyleRenderer instance.
        ///    
        /// 
        public void SetParameters(VisualStyleElement element) { 
            if (element == null) {
                throw new ArgumentNullException("element"); 
            } 

            SetParameters(element.ClassName, element.Part, element.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 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; 
        }

        /// 
        ///  
        ///    
        ///       [See win32 equivalent.] 
        ///     
        /// 
        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.]
        ///       This method uses Graphics.DrawImage as a backup if themed drawing does not work.
        ///    
        ///  
        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);
            //} 
        } 

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

        /// 
        /// 
        ///     
        ///       [See win32 equivalent.]
        ///     
        ///  
        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);
        }
 
        /// 
        ///  
        ///     
        ///       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.]
        ///    
        /// 
        [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. 

 		if (hRegion == IntPtr.Zero) { 
			return null; 
		}
 
		// From the GDI+ sources it doesn't appear as if they take ownership of the hRegion, so this is safe to do.
 		// We need to DeleteObject in order to not leak. DevDiv Bugs 169791
		Region region = Region.FromHrgn(hRegion);
 		SafeNativeMethods.ExternalDeleteObject(new HandleRef(null, hRegion)); 
 		return region;
 
        } 

        ///  
        /// 
        ///    
        ///       [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.]
        ///       Returns null if the returned font was not true type, since GDI+ does not support it.
        ///    
        ///  
        [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.] 
        ///    
        /// 
        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)); 
        }
 
        /// 
        /// 
        ///  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;
            } 
        }

        /// 
        ///  
        ///    
        ///       Instantiates the ThemeHandle cache hashtable. 
        ///     
        /// 
        private static void CreateThemeHandleHashtable() { 
            themeHandles = new Hashtable(numberOfPossibleClasses);
        }

        ///  
        /// 
        ///     
        ///       Handles the ThemeChanged event. Basically, we need to ensure all per-thread theme handle 
        ///       caches are refreshed.
        ///     
        /// 
        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++;
            } 
        }

        /// 
        ///  
        ///    
        ///     Refreshes this thread's theme handle cache. 
        ///     
        /// 
        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);
        } 

        ///  
        ///  
        ///    
        ///     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.
        ///    
        /// 
        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.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK