WindowsGraphics.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Misc / GDI / WindowsGraphics.cs / 1 / WindowsGraphics.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
//#define GDI_FINALIZATION_WATCH 

// THIS PARTIAL CLASS CONTAINS THE BASE METHODS FOR CREATING AND DISPOSING A WINDOWSGRAPHICS AS WELL 
// GETTING, DISPOSING AND WORKING WITH A DC.

#if WINFORMS_NAMESPACE
namespace System.Windows.Forms.Internal 
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal 
#else 
namespace System.Experimental.Gdi
#endif 
{
    using System;
    using System.Internal;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Drawing;
    using System.Drawing.Drawing2D; 

    /// 
    /// 
    ///     WindowsGraphics is a library for rendering text and drawing using GDI; it was 
    ///     created to address performance and compatibility issues found in GDI+ Graphics
    ///     class. 
    /// 
    ///     Note: WindowsGraphics is a stateful component, DC properties are persisted from
    ///     method calls, as opposed to Graphics (GDI+) which performs attomic operations and 
    ///     always restores the hdc.
    ///     The underlying hdc is always saved and restored on dispose so external HDCs won't
    ///     be modified by WindowsGraphics.  So we don't need to restore previous objects into
    ///     the dc in method calls. 
    ///     See VSWhidbey 300692 & 445469 for some background.
    /// 
#if WINFORMS_PUBLIC_GRAPHICS_LIBRARY 
    public
#else 
    internal
#endif
    sealed partial class WindowsGraphics : MarshalByRefObject, IDisposable, IDeviceContext
    { 
        // Wrapper around the window dc this object refers to.
        // Note: this dc is only disposed when owned (created) by the WindowsGraphics. 
        DeviceContext dc; 
        bool disposeDc;
        Graphics graphics; // cached when initialized FromGraphics to be able to call g.ReleaseHdc from Dispose. 

#if GDI_FINALIZATION_WATCH
        private string AllocationSite = DbgUtil.StackTrace;
#endif 

        // Construction/destruction API 
 
        /// 
        public WindowsGraphics( DeviceContext dc ) 
        {
            Debug.Assert( dc != null, "null dc!");
            this.dc = dc;
            this.dc.SaveHdc(); 
            //this.disposeDc = false; // the dc is not owned by this object.
        } 
 
        /// 
        ///     Creates a WindowsGraphics from a memory DeviceContext object compatible with the primary screen device. 
        ///     This object is suitable for performing text measuring but not for drawing into it because it does
        ///     not have a backup bitmap.
        /// 
        public static WindowsGraphics CreateMeasurementWindowsGraphics() 
        {
            DeviceContext dc = DeviceContext.FromCompatibleDC(IntPtr.Zero); 
            WindowsGraphics wg = new WindowsGraphics(dc); 
            wg.disposeDc = true; // we create it, we dispose it.
 
            return wg;
        }

        ///  
        public static WindowsGraphics FromHwnd(IntPtr hWnd)
        { 
            DeviceContext dc = DeviceContext.FromHwnd( hWnd ); 
            WindowsGraphics wg = new WindowsGraphics( dc );
            wg.disposeDc = true; // we create it, we dispose it. 

            return wg;
        }
 
        /// 
        public static WindowsGraphics FromHdc(IntPtr hDc) 
        { 
            Debug.Assert( hDc != IntPtr.Zero, "null hDc" );
 
            DeviceContext dc = DeviceContext.FromHdc(hDc);
            WindowsGraphics wg = new WindowsGraphics( dc );
            wg.disposeDc = true; // we create it, we dispose it.
 
            return wg;
        } 
 
        /// 
        ///     Creates a WindowsGraphics object from a Graphics object.  Clipping and coordinate transforms 
        ///     are preserved.
        ///
        ///     Notes:
        ///     - The passed Graphics object cannot be used until the WindowsGraphics is disposed 
        ///     since it borrows the hdc from the Graphics object locking it.
        ///     - Changes to the hdc using the WindowsGraphics object are not preserved into the Graphics object; 
        ///     the hdc is returned to the Graphics object intact. 
        ///
        ///     Some background about how Graphics uses the internal hdc when created from an existing one 
        ///     (mail from GillesK from GDI+ team):
        ///     User has an HDC with a particular state:
        ///     Graphics object gets created based on that HDC. We query the HDC for its state and apply it to the Graphics.
        ///     At this stage, we do a SaveHDC and clear everything out of it. 
        ///     User calls GetHdc. We restore the HDC to the state it was in and give it to the user.
        ///     User calls ReleaseHdc, we save the current state of the HDC and clear everything 
        ///     (so that the graphics state gets applied next time we use it). 
        ///     Next time the user calls GetHdc we give him back the state after the second ReleaseHdc.
        ///     (But the state changes between the GetHdc and ReleaseHdc are not applied to the Graphics). 
        ///     Please note that this only applies the HDC created graphics, for Bitmap derived graphics, GetHdc creates a new DIBSection and
        ///     things get a lot more complicated.
        /// 
        public static WindowsGraphics FromGraphics(Graphics g) 
        {
            ApplyGraphicsProperties properties = ApplyGraphicsProperties.All; 
            return WindowsGraphics.FromGraphics(g, properties); 
        }
 
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert( g != null, "null Graphics object." );
            //Debug.Assert( properties != ApplyGraphicsProperties.None, "Consider using other WindowsGraphics constructor if not preserving Graphics properties." ); 

            WindowsRegion wr = null; 
            float[] elements = null; 

            Region clipRgn = null; 
            Matrix worldTransf = null;

            if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0 || (properties & ApplyGraphicsProperties.Clipping) != 0)
            { 
                object[] data = g.GetContextInfo() as object[];
 
                if( data != null && data.Length == 2 ) 
                {
                    clipRgn = data[0] as Region; 
                    worldTransf = data[1] as Matrix;
                }

                if( worldTransf != null ) 
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0) 
                    { 
                        elements = worldTransf.Elements;
                    } 
                    worldTransf.Dispose();
                }

                if( clipRgn != null ) 
                {
                    if ((properties & ApplyGraphicsProperties.Clipping) != 0) 
                    { 
                        // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                        // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us. 
                        // (no try-finally block since this method is used frequently - perf).
                        // See VSWhidbey#383762
                        // If the Graphics.Clip has not been set (Region.IsInfinite) we don't need to apply it to the DC.
                        if (!clipRgn.IsInfinite(g)) 
                        {
                            wr = WindowsRegion.FromRegion(clipRgn, g); // WindowsRegion will take ownership of the hRegion. 
                        } 
                    }
                    clipRgn.Dispose(); // Disposing the Region object doesn't destroy the hRegion. 
                }
            }

            WindowsGraphics wg = WindowsGraphics.FromHdc( g.GetHdc() ); // This locks the Graphics object. 
            wg.graphics = g;
 
            // Apply transform and clip 
            if (wr != null)
            { 
                using (wr)
                {
                    // If the Graphics object was created from a native DC the actual clipping region is the intersection
                    // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as 
                    // Graphics.VisibleClipBounds. See VSW#490404.
                    wg.DeviceContext.IntersectClip(wr); 
 
                }
            } 

            if (elements != null)
            {
                // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset. 
                wg.DeviceContext.TranslateTransform((int)elements[4], (int)elements[5]);
            } 
 
            return wg;
        } 

        /// 
        ~WindowsGraphics()
        { 
            Dispose(false);
        } 
 
        public DeviceContext DeviceContext
        { 
            get
            {
                return this.dc;
            } 
        }
 
 
        /// 
        // Okay to suppress. From [....]: 
        //"WindowsGraphics object does not own the Graphics object.  For instance in a control’s Paint event we pass the
        //GraphicsContainer object to TextRenderer, which uses WindowsGraphics;
        //if the Graphics object is disposed then further painting will be broken."
        [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] 
        public void Dispose()
        { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 

        [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")]
        internal void Dispose(bool disposing)
        { 
            if (this.dc != null )
            { 
                DbgUtil.AssertFinalization(this, disposing); 

                try 
                {
                    // Restore original dc.
                    this.dc.RestoreHdc();
 
                    if( this.disposeDc)
                    { 
                        this.dc.Dispose(disposing); 
                    }
 
                    if( this.graphics != null )    // if created from a Graphics object...
                    {
                        this.graphics.ReleaseHdcInternal(this.dc.Hdc);
                        this.graphics = null; 
                    }
 
                } 
                catch(Exception ex )
                { 
                    if( ClientUtils.IsSecurityOrCriticalException( ex ) )
                    {
                        throw; // rethrow the original exception.
                    } 
                    Debug.Fail("Exception thrown during disposing: \r\n" + ex.ToString());
                } 
                finally { 
                    this.dc = null;
                } 
            }
        }

        ///  
        public IntPtr GetHdc()
        { 
            return this.dc.Hdc; 
        }
 
        /// 
        public void ReleaseHdc()
        {
            this.dc.Dispose(); 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
//#define GDI_FINALIZATION_WATCH 

// THIS PARTIAL CLASS CONTAINS THE BASE METHODS FOR CREATING AND DISPOSING A WINDOWSGRAPHICS AS WELL 
// GETTING, DISPOSING AND WORKING WITH A DC.

#if WINFORMS_NAMESPACE
namespace System.Windows.Forms.Internal 
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal 
#else 
namespace System.Experimental.Gdi
#endif 
{
    using System;
    using System.Internal;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Drawing;
    using System.Drawing.Drawing2D; 

    /// 
    /// 
    ///     WindowsGraphics is a library for rendering text and drawing using GDI; it was 
    ///     created to address performance and compatibility issues found in GDI+ Graphics
    ///     class. 
    /// 
    ///     Note: WindowsGraphics is a stateful component, DC properties are persisted from
    ///     method calls, as opposed to Graphics (GDI+) which performs attomic operations and 
    ///     always restores the hdc.
    ///     The underlying hdc is always saved and restored on dispose so external HDCs won't
    ///     be modified by WindowsGraphics.  So we don't need to restore previous objects into
    ///     the dc in method calls. 
    ///     See VSWhidbey 300692 & 445469 for some background.
    /// 
#if WINFORMS_PUBLIC_GRAPHICS_LIBRARY 
    public
#else 
    internal
#endif
    sealed partial class WindowsGraphics : MarshalByRefObject, IDisposable, IDeviceContext
    { 
        // Wrapper around the window dc this object refers to.
        // Note: this dc is only disposed when owned (created) by the WindowsGraphics. 
        DeviceContext dc; 
        bool disposeDc;
        Graphics graphics; // cached when initialized FromGraphics to be able to call g.ReleaseHdc from Dispose. 

#if GDI_FINALIZATION_WATCH
        private string AllocationSite = DbgUtil.StackTrace;
#endif 

        // Construction/destruction API 
 
        /// 
        public WindowsGraphics( DeviceContext dc ) 
        {
            Debug.Assert( dc != null, "null dc!");
            this.dc = dc;
            this.dc.SaveHdc(); 
            //this.disposeDc = false; // the dc is not owned by this object.
        } 
 
        /// 
        ///     Creates a WindowsGraphics from a memory DeviceContext object compatible with the primary screen device. 
        ///     This object is suitable for performing text measuring but not for drawing into it because it does
        ///     not have a backup bitmap.
        /// 
        public static WindowsGraphics CreateMeasurementWindowsGraphics() 
        {
            DeviceContext dc = DeviceContext.FromCompatibleDC(IntPtr.Zero); 
            WindowsGraphics wg = new WindowsGraphics(dc); 
            wg.disposeDc = true; // we create it, we dispose it.
 
            return wg;
        }

        ///  
        public static WindowsGraphics FromHwnd(IntPtr hWnd)
        { 
            DeviceContext dc = DeviceContext.FromHwnd( hWnd ); 
            WindowsGraphics wg = new WindowsGraphics( dc );
            wg.disposeDc = true; // we create it, we dispose it. 

            return wg;
        }
 
        /// 
        public static WindowsGraphics FromHdc(IntPtr hDc) 
        { 
            Debug.Assert( hDc != IntPtr.Zero, "null hDc" );
 
            DeviceContext dc = DeviceContext.FromHdc(hDc);
            WindowsGraphics wg = new WindowsGraphics( dc );
            wg.disposeDc = true; // we create it, we dispose it.
 
            return wg;
        } 
 
        /// 
        ///     Creates a WindowsGraphics object from a Graphics object.  Clipping and coordinate transforms 
        ///     are preserved.
        ///
        ///     Notes:
        ///     - The passed Graphics object cannot be used until the WindowsGraphics is disposed 
        ///     since it borrows the hdc from the Graphics object locking it.
        ///     - Changes to the hdc using the WindowsGraphics object are not preserved into the Graphics object; 
        ///     the hdc is returned to the Graphics object intact. 
        ///
        ///     Some background about how Graphics uses the internal hdc when created from an existing one 
        ///     (mail from GillesK from GDI+ team):
        ///     User has an HDC with a particular state:
        ///     Graphics object gets created based on that HDC. We query the HDC for its state and apply it to the Graphics.
        ///     At this stage, we do a SaveHDC and clear everything out of it. 
        ///     User calls GetHdc. We restore the HDC to the state it was in and give it to the user.
        ///     User calls ReleaseHdc, we save the current state of the HDC and clear everything 
        ///     (so that the graphics state gets applied next time we use it). 
        ///     Next time the user calls GetHdc we give him back the state after the second ReleaseHdc.
        ///     (But the state changes between the GetHdc and ReleaseHdc are not applied to the Graphics). 
        ///     Please note that this only applies the HDC created graphics, for Bitmap derived graphics, GetHdc creates a new DIBSection and
        ///     things get a lot more complicated.
        /// 
        public static WindowsGraphics FromGraphics(Graphics g) 
        {
            ApplyGraphicsProperties properties = ApplyGraphicsProperties.All; 
            return WindowsGraphics.FromGraphics(g, properties); 
        }
 
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert( g != null, "null Graphics object." );
            //Debug.Assert( properties != ApplyGraphicsProperties.None, "Consider using other WindowsGraphics constructor if not preserving Graphics properties." ); 

            WindowsRegion wr = null; 
            float[] elements = null; 

            Region clipRgn = null; 
            Matrix worldTransf = null;

            if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0 || (properties & ApplyGraphicsProperties.Clipping) != 0)
            { 
                object[] data = g.GetContextInfo() as object[];
 
                if( data != null && data.Length == 2 ) 
                {
                    clipRgn = data[0] as Region; 
                    worldTransf = data[1] as Matrix;
                }

                if( worldTransf != null ) 
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0) 
                    { 
                        elements = worldTransf.Elements;
                    } 
                    worldTransf.Dispose();
                }

                if( clipRgn != null ) 
                {
                    if ((properties & ApplyGraphicsProperties.Clipping) != 0) 
                    { 
                        // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                        // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us. 
                        // (no try-finally block since this method is used frequently - perf).
                        // See VSWhidbey#383762
                        // If the Graphics.Clip has not been set (Region.IsInfinite) we don't need to apply it to the DC.
                        if (!clipRgn.IsInfinite(g)) 
                        {
                            wr = WindowsRegion.FromRegion(clipRgn, g); // WindowsRegion will take ownership of the hRegion. 
                        } 
                    }
                    clipRgn.Dispose(); // Disposing the Region object doesn't destroy the hRegion. 
                }
            }

            WindowsGraphics wg = WindowsGraphics.FromHdc( g.GetHdc() ); // This locks the Graphics object. 
            wg.graphics = g;
 
            // Apply transform and clip 
            if (wr != null)
            { 
                using (wr)
                {
                    // If the Graphics object was created from a native DC the actual clipping region is the intersection
                    // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as 
                    // Graphics.VisibleClipBounds. See VSW#490404.
                    wg.DeviceContext.IntersectClip(wr); 
 
                }
            } 

            if (elements != null)
            {
                // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset. 
                wg.DeviceContext.TranslateTransform((int)elements[4], (int)elements[5]);
            } 
 
            return wg;
        } 

        /// 
        ~WindowsGraphics()
        { 
            Dispose(false);
        } 
 
        public DeviceContext DeviceContext
        { 
            get
            {
                return this.dc;
            } 
        }
 
 
        /// 
        // Okay to suppress. From [....]: 
        //"WindowsGraphics object does not own the Graphics object.  For instance in a control’s Paint event we pass the
        //GraphicsContainer object to TextRenderer, which uses WindowsGraphics;
        //if the Graphics object is disposed then further painting will be broken."
        [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] 
        public void Dispose()
        { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 

        [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")]
        internal void Dispose(bool disposing)
        { 
            if (this.dc != null )
            { 
                DbgUtil.AssertFinalization(this, disposing); 

                try 
                {
                    // Restore original dc.
                    this.dc.RestoreHdc();
 
                    if( this.disposeDc)
                    { 
                        this.dc.Dispose(disposing); 
                    }
 
                    if( this.graphics != null )    // if created from a Graphics object...
                    {
                        this.graphics.ReleaseHdcInternal(this.dc.Hdc);
                        this.graphics = null; 
                    }
 
                } 
                catch(Exception ex )
                { 
                    if( ClientUtils.IsSecurityOrCriticalException( ex ) )
                    {
                        throw; // rethrow the original exception.
                    } 
                    Debug.Fail("Exception thrown during disposing: \r\n" + ex.ToString());
                } 
                finally { 
                    this.dc = null;
                } 
            }
        }

        ///  
        public IntPtr GetHdc()
        { 
            return this.dc.Hdc; 
        }
 
        /// 
        public void ReleaseHdc()
        {
            this.dc.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