DeviceContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Misc / GDI / DeviceContext.cs / 1305376 / DeviceContext.cs

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

//#define TRACK_HDC 
//#define GDI_FINALIZATION_WATCH 

#if [....]_NAMESPACE 
namespace System.Windows.Forms.Internal
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal
#else 
namespace System.Experimental.Gdi
#endif 
{ 
    using System;
    using System.Collections; 
    using System.Internal;
    using System.Security;
    using System.Runtime.InteropServices;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Drawing; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Runtime.Versioning; 

    /// 
    /// 
    ///     Represents a Win32 device context.  Provides operations for setting some of the properties 
    ///     of a device context.  It's the managed wrapper for an HDC.
    /// 
    ///     This class is divided into two files separating the code that needs to be compiled into 
    ///     reatail builds and debugging code.
    ///  
#if [....]_PUBLIC_GRAPHICS_LIBRARY
    public
#else
    internal 
#endif
    sealed partial class DeviceContext : MarshalByRefObject, IDeviceContext, IDisposable 
    { 
        /// 
        ///     This class is a wrapper to a Win32 device context, and the Hdc property is the way to get a 
        ///     handle to it.
        ///
        ///     The hDc is released/deleted only when owned by the object, meaning it was created internally;
        ///     in this case, the object is responsible for releasing/deleting it. 
        ///     In the case the object is created from an exisiting hdc, it is not released; this is consistent
        ///     with the Win32 guideline that says if you call GetDC/CreateDC/CreatIC/CreateEnhMetafile, you are 
        ///     responsible for calling ReleaseDC/DeleteDC/DeleteEnhMetafile respectivelly. 
        ///
        ///     This class implements some of the operations commonly performed on the properties of a dc  in [....], 
        ///     specially for interacting with GDI+, like clipping and coordinate transformation.
        ///     Several properties are not persisted in the dc but instead they are set/reset during a more comprehensive
        ///     operation like text rendering or painting; for instance text alignment is set and reset during DrawText (GDI),
        ///     DrawString (GDI+). 
        ///
        ///     Other properties are persisted from operation to operation until they are reset, like clipping, 
        ///     one can make several calls to Graphics or WindowsGraphics obect after setting the dc clip area and 
        ///     before resetting it; these kinds of properties are the ones implemented in this class.
        ///     This kind of properties place an extra chanllenge in the scenario where a DeviceContext is obtained 
        ///     from a Graphics object that has been used with GDI+, because GDI+ saves the hdc internally, rendering the
        ///     DeviceContext underlying hdc out of [....].  DeviceContext needs to support these kind of properties to
        ///     be able to keep the GDI+ and GDI HDCs in [....].
        /// 
        ///     A few other persisting properties have been implemented in DeviceContext2, among them:
        ///     1. Window origin. 
        ///     2. Bounding rectangle. 
        ///     3. DC origin.
        ///     4. View port extent. 
        ///     5. View port origin.
        ///     6. Window extent
        ///
        ///     Other non-persisted properties just for information: Background/Forground color, Palette, Color adjustment, 
        ///     Color space, ICM mode and profile, Current pen position, Binary raster op (not supported by GDI+),
        ///     Background mode, Logical Pen, DC pen color, ARc direction, Miter limit, Logical brush, DC brush color, 
        ///     Brush origin, Polygon filling mode, Bitmap stretching mode, Logical font, Intercharacter spacing, 
        ///     Font mapper flags, Text alignment, Test justification, Layout, Path, Meta region.
        ///     See book "Windows Graphics Programming - Feng Yuang", P315 - Device Context Attributes. 
        /// 

        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
        IntPtr hDC; 
        DeviceContextType dcType;
 
        public event EventHandler Disposing; 

        bool disposed; 

        // We cache the hWnd when creating the dc from one, to provide support forIDeviceContext.GetHdc/ReleaseHdc.
        // This hWnd could be null, in such case it is referring to the screen.
        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 
        IntPtr hWnd = (IntPtr) (-1); // Unlikely to be a valid hWnd.
 
        IntPtr hInitialPen; 
        IntPtr hInitialBrush;
        IntPtr hInitialBmp; 
        IntPtr hInitialFont;

        IntPtr hCurrentPen;
        IntPtr hCurrentBrush; 
        IntPtr hCurrentBmp;
        IntPtr hCurrentFont; 
 
        Stack  contextStack;
 
#if GDI_FINALIZATION_WATCH
        private string AllocationSite = DbgUtil.StackTrace;
        private string DeAllocationSite = "";
#endif 

        /// 
        /// Class properties... 
        ///
 
        /// 
        ///     Specifies whether a modification has been applied to the dc, like setting the clipping area or a coordinate transform.
        /// 
 
        /// 
        ///     The device type the context refers to. 
        ///  
        public DeviceContextType DeviceContextType
        { 
            get
            {
                return this.dcType;
            } 
        }
 
        ///  
        ///     This object's hdc.  If this property is called, then the object will be used as an HDC wrapper,
        ///     so the hdc is cached and calls to GetHdc/ReleaseHdc won't PInvoke into GDI. 
        ///     Call Dispose to properly release the hdc.
        /// 
        public IntPtr Hdc
        { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            get 
            {
                if( this.hDC == IntPtr.Zero ) 
                {
                    if( this.dcType == DeviceContextType.Display )
                    {
                        Debug.Assert(!this.disposed, "Accessing a disposed DC, forcing recreation of HDC - this will generate a Handle leak!"); 

                        // Note: ReleaseDC must be called from the same thread. This applies only to HDC obtained 
                        // from calling GetDC. This means Display DeviceContext objects should never be finalized. 
                        this.hDC = ((IDeviceContext)this).GetHdc();  // this.hDC will be released on call to Dispose.
                        CacheInitialState(); 
                    }
#if GDI_FINALIZATION_WATCH
                    else
                    { 
                        try { Debug.WriteLine(string.Format("Allocation stack:\r\n{0}\r\nDeallocation stack:\r\n{1}", AllocationSite, DeAllocationSite)); } catch  {}
                    } 
#endif 
                }
 
                Debug.Assert( this.hDC != IntPtr.Zero, "Attempt to use deleted HDC - DC type: " + this.dcType );

                return this.hDC;
            } 
        }
 
        // VSWhidbey 536325 
        // Due to a problem with calling DeleteObject() on currently selected GDI objects,
        // we now track the initial set of objects when a DeviceContext is created.  Then, 
        // we also track which objects are currently selected in the DeviceContext.  When
        // a currently selected object is disposed, it is first replaced in the DC and then
        // deleted.
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private void CacheInitialState() 
        { 
            Debug.Assert(this.hDC != IntPtr.Zero, "Cannot get initial state without a valid HDC");
            hCurrentPen   = hInitialPen   = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_PEN); 
            hCurrentBrush = hInitialBrush = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_BRUSH);
            hCurrentBmp   = hInitialBmp   = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_BITMAP);
            hCurrentFont  = hInitialFont  = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_FONT);
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public void DeleteObject(IntPtr handle, GdiObjectType type) {
            IntPtr handleToDelete = IntPtr.Zero; 
            switch (type) {
                case GdiObjectType.Pen:
                    if (handle == hCurrentPen) {
                        IntPtr currentPen = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialPen)); 
                        Debug.Assert(currentPen == hCurrentPen, "DeviceContext thinks a different pen is selected than the HDC");
                        hCurrentPen = IntPtr.Zero; 
                    } 
                    handleToDelete = handle;
                    break; 
                case GdiObjectType.Brush:
                    if (handle == hCurrentBrush) {
                        IntPtr currentBrush = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialBrush));
                        Debug.Assert(currentBrush == hCurrentBrush, "DeviceContext thinks a different brush is selected than the HDC"); 
                        hCurrentBrush = IntPtr.Zero;
                    } 
                    handleToDelete = handle; 
                    break;
                case GdiObjectType.Bitmap: 
                    if (handle == hCurrentBmp) {
                        IntPtr currentBmp = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialBmp));
                        Debug.Assert(currentBmp == hCurrentBmp, "DeviceContext thinks a different brush is selected than the HDC");
                        hCurrentBmp = IntPtr.Zero; 
                    }
                    handleToDelete = handle; 
                    break; 
            }
 
            IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, handleToDelete));
        }

        // 
        // object construction API.  Publicly constructable from static methods only.
        // 
 
        /// 
        ///     Constructor to contruct a DeviceContext object from an window handle. 
        /// 
        private DeviceContext(IntPtr hWnd)
        {
            this.hWnd   = hWnd; 
            this.dcType = DeviceContextType.Display;
 
            DeviceContexts.AddDeviceContext(this); 

            // the hDc will be created on demand. 

#if TRACK_HDC
            Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeviceContext( hWnd=0x{0:x8} )", (int) hWnd)));
#endif 
        }
 
        ///  
        ///     Constructor to contruct a DeviceContext object from an existing Win32 device context handle.
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private DeviceContext(IntPtr hDC, DeviceContextType dcType)
        { 
            this.hDC    = hDC;
            this.dcType = dcType; 
 
            CacheInitialState();
            DeviceContexts.AddDeviceContext(this); 

            if( dcType == DeviceContextType.Display )
            {
                this.hWnd = IntUnsafeNativeMethods.WindowFromDC( new HandleRef( this, this.hDC) ); 
            }
#if TRACK_HDC 
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DeviceContext( hDC=0x{0:X8}, Type={1} )", (int) hDC, dcType) )); 
#endif
        } 

        //

 
        //
 
 
        /// 
        ///     CreateDC creates a DeviceContext object wrapping an hdc created with the Win32 CreateDC function. 
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static DeviceContext CreateDC(string driverName, string deviceName, string fileName, HandleRef devMode) 
        {
            // Note: All input params can be null but not at the same time.  See MSDN for information. 
 
            IntPtr hdc = IntUnsafeNativeMethods.CreateDC(driverName, deviceName, fileName, devMode);
            return new DeviceContext( hdc, DeviceContextType.NamedDevice ); 
        }

        /// 
        ///     CreateIC creates a DeviceContext object wrapping an hdc created with the Win32 CreateIC function. 
        /// 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static DeviceContext CreateIC(string driverName, string deviceName, string fileName, HandleRef devMode)
        { 
            // Note: All input params can be null but not at the same time.  See MSDN for information.

            IntPtr hdc = IntUnsafeNativeMethods.CreateIC(driverName, deviceName, fileName, devMode);
            return new DeviceContext( hdc, DeviceContextType.Information ); 
        }
 
        ///  
        ///     Creates a DeviceContext object wrapping a memory DC compatible with the specified device.
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static DeviceContext FromCompatibleDC(IntPtr hdc)
        { 

 
            // If hdc is null, the function creates a memory DC compatible with the application's current screen. 
            // Win2K+: (See CreateCompatibleDC in the MSDN).
            // In this case the thread that calls CreateCompatibleDC owns the HDC that is created. When this thread is destroyed, 
            // the HDC is no longer valid.

            IntPtr compatibleDc = IntUnsafeNativeMethods.CreateCompatibleDC( new HandleRef(null, hdc) );
            return new DeviceContext(compatibleDc, DeviceContextType.Memory); 
        }
 
        ///  
        /// 
        ///     Used for wrapping an existing hdc.  In this case, this object doesn't own the hdc 
        ///     so calls to GetHdc/ReleaseHdc don't PInvoke into GDI.
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static DeviceContext FromHdc(IntPtr hdc)
        { 
            Debug.Assert( hdc != IntPtr.Zero, "hdc == 0" ); 
            return new DeviceContext(hdc, DeviceContextType.Unknown);
        } 

        /// 
        /// 
        ///     When hwnd is null, we are getting the screen DC. 
        /// 
        public static DeviceContext FromHwnd( IntPtr hwnd ) 
        { 
            return new DeviceContext(hwnd);
        } 


        /// 
        ~DeviceContext() 
        {
            Dispose(false); 
        } 

        ///  
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        ///  
        internal void Dispose(bool disposing)
        { 
            if (disposed)
            {
                return;
            } 

            if (this.Disposing != null) 
            { 
                this.Disposing(this, EventArgs.Empty);
            } 

            this.disposed = true;

#if !DRAWING_NAMESPACE 
            DisposeFont(disposing);
#endif 
 
            switch( this.dcType )
            { 
                case DeviceContextType.Display:
                    Debug.Assert( disposing, "WARNING: Finalizing a Display DeviceContext.\r\nReleaseDC may fail when not called from the same thread GetDC was called from." );

                    ((IDeviceContext)this).ReleaseHdc(); 
                    break;
 
                case DeviceContextType.Information: 
                case DeviceContextType.NamedDevice:
 
                    // CreateDC and CreateIC add an HDC handle to the HandleCollector; to remove it properly we need
                    // to call DeleteHDC.
#if TRACK_HDC
                    Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DC.DeleteHDC(hdc=0x{0:x8})", (int) this.hDC))); 
#endif
 
                    IntUnsafeNativeMethods.DeleteHDC(new HandleRef(this, this.hDC)); 

                    this.hDC = IntPtr.Zero; 
                    break;

                case DeviceContextType.Memory:
 
                    // CreatCompatibleDC adds a GDI handle to HandleCollector, to remove it properly we need to call
                    // DeleteDC. 
#if TRACK_HDC 
                    Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DC.DeleteDC(hdc=0x{0:x8})", (int) this.hDC)));
#endif 
                    IntUnsafeNativeMethods.DeleteDC(new HandleRef(this, this.hDC));

                    this.hDC = IntPtr.Zero;
                    break; 

                // case DeviceContextType.Metafile: - not yet supported. 
#if [....]_PUBLIC_GRAPHICS_LIBRARY 
                case DeviceContextType.Metafile:
                    IntUnsafeNativeMethods.CloseEnhMetaFile(new HandleRef(this, this.Hdc)); 

                    this.hDC = IntPtr.Zero;
                    break;
#endif 
                case DeviceContextType.Unknown:
                default: 
                    return; 
                    // do nothing, the hdc is not owned by this object.
                    // in this case it is ok if disposed throught finalization. 
            }

            DbgUtil.AssertFinalization(this, disposing);
        } 

        ///  
        ///  
        ///     Explicit interface method implementation to hide them a bit for usability reasons so the object is seen
        ///     as a wrapper around an hdc that is always available, and for performance reasons since it caches the hdc 
        ///     if used in this way.
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        IntPtr IDeviceContext.GetHdc()
        { 
            if (this.hDC == IntPtr.Zero) 
            {
                Debug.Assert( this.dcType == DeviceContextType.Display, "Calling GetDC from a non display/window device." ); 

                // Note: for common DCs, GetDC assigns default attributes to the DC each time it is retrieved.
                // For example, the default font is System.
                this.hDC = IntUnsafeNativeMethods.GetDC(new HandleRef(this, this.hWnd)); 
#if TRACK_HDC
                Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("hdc[0x{0:x8}]=DC.GetHdc(hWnd=0x{1:x8})", (int) this.hDC, (int) this.hWnd))); 
#endif 
            }
 
            return this.hDC;
        }

 
        /// 
        /// 
        ///     If the object was created from a DC, this object doesn't 'own' the dc so we just ignore 
        ///     this call.
        /// 
        void IDeviceContext.ReleaseHdc()
        {
            if (this.hDC != IntPtr.Zero && this.dcType == DeviceContextType.Display)
            { 
#if TRACK_HDC
                int retVal = 
#endif 
                IntUnsafeNativeMethods.ReleaseDC(new HandleRef(this, this.hWnd), new HandleRef(this, this.hDC));
                // Note: retVal == 0 means it was not released but doesn't necessarily means an error; class or private DCs are never released. 
#if TRACK_HDC
                Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("[ret={0}]=DC.ReleaseDC(hDc=0x{1:x8}, hWnd=0x{2:x8})", retVal, (int) this.hDC, (int) this.hWnd)));
#endif
                this.hDC = IntPtr.Zero; 
            }
        } 
 

        ///  
        ///     Specifies whether the DC is in GM_ADVANCE mode (supported only in NT platforms).
        ///     If false, it is in GM_COMPATIBLE mode.
        /// 
        public DeviceContextGraphicsMode GraphicsMode 
        {
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get
            { 
                return (DeviceContextGraphicsMode) IntUnsafeNativeMethods.GetGraphicsMode( new HandleRef( this, this.Hdc ) );
            }
#if [....]_PUBLIC_GRAPHICS_LIBRARY
            set 
            {
                SetGraphicsMode(value); 
            } 
#endif
        } 

        /// 
        ///     Sets the dc graphics mode and returns the old value.
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public DeviceContextGraphicsMode SetGraphicsMode(DeviceContextGraphicsMode newMode) 
        {
            return (DeviceContextGraphicsMode) IntUnsafeNativeMethods.SetGraphicsMode( new HandleRef( this, this.Hdc ), (int) newMode ); 
        }

        /// 
        ///     Restores the device context to the specified state. The DC is restored by popping state information off a 
        ///     stack created by earlier calls to the SaveHdc function.
        ///     The stack can contain the state information for several instances of the DC. If the state specified by the 
        ///     specified parameter is not at the top of the stack, RestoreDC deletes all state information between the top 
        ///     of the stack and the specified instance.
        ///     Specifies the saved state to be restored. If this parameter is positive, nSavedDC represents a specific 
        ///     instance of the state to be restored. If this parameter is negative, nSavedDC represents an instance relative
        ///     to the current state. For example, -1 restores the most recently saved state.
        ///     See MSDN for more info.
        ///  
        public void RestoreHdc()
        { 
#if TRACK_HDC 
            bool result =
#endif 
            // Note: Don't use the Hdc property here, it would force handle creation.
            IntUnsafeNativeMethods.RestoreDC(new HandleRef(this, this.hDC), -1);
#if TRACK_HDC
            // Note: [....] may call this method during app exit at which point the DC may have been finalized already causing this assert to popup. 
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("ret[0]=DC.RestoreHdc(hDc=0x{1:x8}, state={2})", result, (int) this.hDC, restoreState) ));
#endif 
            Debug.Assert(contextStack != null, "Someone is calling RestoreHdc() before SaveHdc()"); 

            if (contextStack != null) { 
                GraphicsState g = (GraphicsState) contextStack.Pop();

                hCurrentBmp     = g.hBitmap;
                hCurrentBrush   = g.hBrush; 
                hCurrentPen     = g.hPen;
                hCurrentFont    = g.hFont; 
 
#if !DRAWING_NAMESPACE
                if (g.font != null && g.font.IsAlive) { 
                    selectedFont    = g.font.Target as WindowsFont;
                }
                else {
                    WindowsFont previousFont = selectedFont; 
                    selectedFont = null;
                    if (previousFont != null && MeasurementDCInfo.IsMeasurementDC(this)) { 
                        previousFont.Dispose(); 
                    }
                } 
#endif

            }
 
#if OPTIMIZED_MEASUREMENTDC
            // in this case, GDI will copy back the previously saved font into the DC. 
            // we dont actually know what the font is in our measurement DC so 
            // we need to clear it off.
            MeasurementDCInfo.ResetIfIsMeasurementDC(this.hDC); 
#endif

        }
 
        /// 
        ///     Saves the current state of the device context by copying data describing selected objects and graphic 
        ///     modes (such as the bitmap, brush, palette, font, pen, region, drawing mode, and mapping mode) to a 
        ///     context stack.
        ///     The SaveDC function can be used any number of times to save any number of instances of the DC state. 
        ///     A saved state can be restored by using the RestoreHdc method.
        ///     See MSDN for more details.
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public int SaveHdc() 
        { 
            HandleRef hdc = new HandleRef( this, this.Hdc);
            int state = IntUnsafeNativeMethods.SaveDC(hdc); 

            if (contextStack == null) {
                contextStack = new Stack();
            } 

            GraphicsState g = new GraphicsState(); 
            g.hBitmap = hCurrentBmp; 
            g.hBrush  = hCurrentBrush;
            g.hPen    = hCurrentPen; 
            g.hFont   = hCurrentFont;

#if !DRAWING_NAMESPACE
            g.font    = new WeakReference(selectedFont); 
#endif
 
 
            contextStack.Push(g);
 
#if TRACK_HDC
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("state[0]=DC.SaveHdc(hDc=0x{1:x8})", state, (int) this.hDC) ));
#endif
 
            return state;
        } 
 
        /// 
        ///     Selects a region as the current clipping region for the device context. 
        ///     Remarks (From MSDN):
        ///         - Only a copy of the selected region is used. The region itself can be selected for any number of other device contexts or it can be deleted.
        ///         - The SelectClipRgn function assumes that the coordinates for a region are specified in device units.
        ///         - To remove a device-context's clipping region, specify a NULL region handle. 
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public void SetClip(WindowsRegion region)
        { 
            HandleRef hdc = new HandleRef(this, this.Hdc);
            HandleRef hRegion = new HandleRef(region, region.HRegion);

            IntUnsafeNativeMethods.SelectClipRgn(hdc, hRegion); 
        }
 
        /// 
        ///     Creates a new clipping region from the intersection of the current clipping region and
        ///     the specified rectangle. 
        ///
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public void IntersectClip(WindowsRegion wr) 
        {
            //if the incoming windowsregion is infinite, there is no need to do any intersecting. 
            if (wr.HRegion == IntPtr.Zero) { 
                return;
            } 

            WindowsRegion clip = new WindowsRegion(0,0,0,0);
            try {
                 int result = IntUnsafeNativeMethods.GetClipRgn(new HandleRef( this, this.Hdc), new HandleRef(clip, clip.HRegion)); 

                 // If the function succeeds and there is a clipping region for the given device context, the return value is 1. 
                 if (result == 1) { 
                     Debug.Assert(clip.HRegion != IntPtr.Zero);
                     wr.CombineRegion(clip, wr, RegionCombineMode.AND); //1 = AND (or Intersect) 
                 }

                 SetClip(wr);
            } 
            finally {
                 clip.Dispose(); 
            } 
        }
 
        /// 
        ///     Modifies the viewport origin for a device context using the specified horizontal and vertical offsets in logical units.
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public void TranslateTransform(int dx, int dy) 
        { 
            IntNativeMethods.POINT orgn = new IntNativeMethods.POINT();
            IntUnsafeNativeMethods.OffsetViewportOrgEx( new HandleRef( this, this.Hdc ), dx, dy, orgn ); 
        }

        /// 
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public override bool Equals(object obj) 
        {
            DeviceContext other = obj as DeviceContext; 

            if (other == this)
            {
                return true; 
            }
 
            if (other == null) 
            {
                return false; 
            }

            // Note: Use property instead of field so the HDC is initialized.  Also, this avoid serialization issues (the obj could be a proxy that does not have access to private fields).
            return other.Hdc == this.Hdc; 
        }
 
        ///  
        ///     This allows collections to treat DeviceContext objects wrapping the same HDC as the same objects.
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public override int GetHashCode()
        { 
            return this.Hdc.GetHashCode();
        } 
 

        internal class GraphicsState { 
            internal IntPtr hBrush;
            internal IntPtr hFont;
            internal IntPtr hPen;
            internal IntPtr hBitmap; 
#if !DRAWING_NAMESPACE
            internal WeakReference font; 
#endif 
        }
     } 
}

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

//#define TRACK_HDC 
//#define GDI_FINALIZATION_WATCH 

#if [....]_NAMESPACE 
namespace System.Windows.Forms.Internal
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal
#else 
namespace System.Experimental.Gdi
#endif 
{ 
    using System;
    using System.Collections; 
    using System.Internal;
    using System.Security;
    using System.Runtime.InteropServices;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Drawing; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Runtime.Versioning; 

    /// 
    /// 
    ///     Represents a Win32 device context.  Provides operations for setting some of the properties 
    ///     of a device context.  It's the managed wrapper for an HDC.
    /// 
    ///     This class is divided into two files separating the code that needs to be compiled into 
    ///     reatail builds and debugging code.
    ///  
#if [....]_PUBLIC_GRAPHICS_LIBRARY
    public
#else
    internal 
#endif
    sealed partial class DeviceContext : MarshalByRefObject, IDeviceContext, IDisposable 
    { 
        /// 
        ///     This class is a wrapper to a Win32 device context, and the Hdc property is the way to get a 
        ///     handle to it.
        ///
        ///     The hDc is released/deleted only when owned by the object, meaning it was created internally;
        ///     in this case, the object is responsible for releasing/deleting it. 
        ///     In the case the object is created from an exisiting hdc, it is not released; this is consistent
        ///     with the Win32 guideline that says if you call GetDC/CreateDC/CreatIC/CreateEnhMetafile, you are 
        ///     responsible for calling ReleaseDC/DeleteDC/DeleteEnhMetafile respectivelly. 
        ///
        ///     This class implements some of the operations commonly performed on the properties of a dc  in [....], 
        ///     specially for interacting with GDI+, like clipping and coordinate transformation.
        ///     Several properties are not persisted in the dc but instead they are set/reset during a more comprehensive
        ///     operation like text rendering or painting; for instance text alignment is set and reset during DrawText (GDI),
        ///     DrawString (GDI+). 
        ///
        ///     Other properties are persisted from operation to operation until they are reset, like clipping, 
        ///     one can make several calls to Graphics or WindowsGraphics obect after setting the dc clip area and 
        ///     before resetting it; these kinds of properties are the ones implemented in this class.
        ///     This kind of properties place an extra chanllenge in the scenario where a DeviceContext is obtained 
        ///     from a Graphics object that has been used with GDI+, because GDI+ saves the hdc internally, rendering the
        ///     DeviceContext underlying hdc out of [....].  DeviceContext needs to support these kind of properties to
        ///     be able to keep the GDI+ and GDI HDCs in [....].
        /// 
        ///     A few other persisting properties have been implemented in DeviceContext2, among them:
        ///     1. Window origin. 
        ///     2. Bounding rectangle. 
        ///     3. DC origin.
        ///     4. View port extent. 
        ///     5. View port origin.
        ///     6. Window extent
        ///
        ///     Other non-persisted properties just for information: Background/Forground color, Palette, Color adjustment, 
        ///     Color space, ICM mode and profile, Current pen position, Binary raster op (not supported by GDI+),
        ///     Background mode, Logical Pen, DC pen color, ARc direction, Miter limit, Logical brush, DC brush color, 
        ///     Brush origin, Polygon filling mode, Bitmap stretching mode, Logical font, Intercharacter spacing, 
        ///     Font mapper flags, Text alignment, Test justification, Layout, Path, Meta region.
        ///     See book "Windows Graphics Programming - Feng Yuang", P315 - Device Context Attributes. 
        /// 

        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
        IntPtr hDC; 
        DeviceContextType dcType;
 
        public event EventHandler Disposing; 

        bool disposed; 

        // We cache the hWnd when creating the dc from one, to provide support forIDeviceContext.GetHdc/ReleaseHdc.
        // This hWnd could be null, in such case it is referring to the screen.
        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 
        IntPtr hWnd = (IntPtr) (-1); // Unlikely to be a valid hWnd.
 
        IntPtr hInitialPen; 
        IntPtr hInitialBrush;
        IntPtr hInitialBmp; 
        IntPtr hInitialFont;

        IntPtr hCurrentPen;
        IntPtr hCurrentBrush; 
        IntPtr hCurrentBmp;
        IntPtr hCurrentFont; 
 
        Stack  contextStack;
 
#if GDI_FINALIZATION_WATCH
        private string AllocationSite = DbgUtil.StackTrace;
        private string DeAllocationSite = "";
#endif 

        /// 
        /// Class properties... 
        ///
 
        /// 
        ///     Specifies whether a modification has been applied to the dc, like setting the clipping area or a coordinate transform.
        /// 
 
        /// 
        ///     The device type the context refers to. 
        ///  
        public DeviceContextType DeviceContextType
        { 
            get
            {
                return this.dcType;
            } 
        }
 
        ///  
        ///     This object's hdc.  If this property is called, then the object will be used as an HDC wrapper,
        ///     so the hdc is cached and calls to GetHdc/ReleaseHdc won't PInvoke into GDI. 
        ///     Call Dispose to properly release the hdc.
        /// 
        public IntPtr Hdc
        { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            get 
            {
                if( this.hDC == IntPtr.Zero ) 
                {
                    if( this.dcType == DeviceContextType.Display )
                    {
                        Debug.Assert(!this.disposed, "Accessing a disposed DC, forcing recreation of HDC - this will generate a Handle leak!"); 

                        // Note: ReleaseDC must be called from the same thread. This applies only to HDC obtained 
                        // from calling GetDC. This means Display DeviceContext objects should never be finalized. 
                        this.hDC = ((IDeviceContext)this).GetHdc();  // this.hDC will be released on call to Dispose.
                        CacheInitialState(); 
                    }
#if GDI_FINALIZATION_WATCH
                    else
                    { 
                        try { Debug.WriteLine(string.Format("Allocation stack:\r\n{0}\r\nDeallocation stack:\r\n{1}", AllocationSite, DeAllocationSite)); } catch  {}
                    } 
#endif 
                }
 
                Debug.Assert( this.hDC != IntPtr.Zero, "Attempt to use deleted HDC - DC type: " + this.dcType );

                return this.hDC;
            } 
        }
 
        // VSWhidbey 536325 
        // Due to a problem with calling DeleteObject() on currently selected GDI objects,
        // we now track the initial set of objects when a DeviceContext is created.  Then, 
        // we also track which objects are currently selected in the DeviceContext.  When
        // a currently selected object is disposed, it is first replaced in the DC and then
        // deleted.
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private void CacheInitialState() 
        { 
            Debug.Assert(this.hDC != IntPtr.Zero, "Cannot get initial state without a valid HDC");
            hCurrentPen   = hInitialPen   = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_PEN); 
            hCurrentBrush = hInitialBrush = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_BRUSH);
            hCurrentBmp   = hInitialBmp   = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_BITMAP);
            hCurrentFont  = hInitialFont  = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, hDC), IntNativeMethods.OBJ_FONT);
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public void DeleteObject(IntPtr handle, GdiObjectType type) {
            IntPtr handleToDelete = IntPtr.Zero; 
            switch (type) {
                case GdiObjectType.Pen:
                    if (handle == hCurrentPen) {
                        IntPtr currentPen = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialPen)); 
                        Debug.Assert(currentPen == hCurrentPen, "DeviceContext thinks a different pen is selected than the HDC");
                        hCurrentPen = IntPtr.Zero; 
                    } 
                    handleToDelete = handle;
                    break; 
                case GdiObjectType.Brush:
                    if (handle == hCurrentBrush) {
                        IntPtr currentBrush = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialBrush));
                        Debug.Assert(currentBrush == hCurrentBrush, "DeviceContext thinks a different brush is selected than the HDC"); 
                        hCurrentBrush = IntPtr.Zero;
                    } 
                    handleToDelete = handle; 
                    break;
                case GdiObjectType.Bitmap: 
                    if (handle == hCurrentBmp) {
                        IntPtr currentBmp = IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef( this, hInitialBmp));
                        Debug.Assert(currentBmp == hCurrentBmp, "DeviceContext thinks a different brush is selected than the HDC");
                        hCurrentBmp = IntPtr.Zero; 
                    }
                    handleToDelete = handle; 
                    break; 
            }
 
            IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, handleToDelete));
        }

        // 
        // object construction API.  Publicly constructable from static methods only.
        // 
 
        /// 
        ///     Constructor to contruct a DeviceContext object from an window handle. 
        /// 
        private DeviceContext(IntPtr hWnd)
        {
            this.hWnd   = hWnd; 
            this.dcType = DeviceContextType.Display;
 
            DeviceContexts.AddDeviceContext(this); 

            // the hDc will be created on demand. 

#if TRACK_HDC
            Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeviceContext( hWnd=0x{0:x8} )", (int) hWnd)));
#endif 
        }
 
        ///  
        ///     Constructor to contruct a DeviceContext object from an existing Win32 device context handle.
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private DeviceContext(IntPtr hDC, DeviceContextType dcType)
        { 
            this.hDC    = hDC;
            this.dcType = dcType; 
 
            CacheInitialState();
            DeviceContexts.AddDeviceContext(this); 

            if( dcType == DeviceContextType.Display )
            {
                this.hWnd = IntUnsafeNativeMethods.WindowFromDC( new HandleRef( this, this.hDC) ); 
            }
#if TRACK_HDC 
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DeviceContext( hDC=0x{0:X8}, Type={1} )", (int) hDC, dcType) )); 
#endif
        } 

        //

 
        //
 
 
        /// 
        ///     CreateDC creates a DeviceContext object wrapping an hdc created with the Win32 CreateDC function. 
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static DeviceContext CreateDC(string driverName, string deviceName, string fileName, HandleRef devMode) 
        {
            // Note: All input params can be null but not at the same time.  See MSDN for information. 
 
            IntPtr hdc = IntUnsafeNativeMethods.CreateDC(driverName, deviceName, fileName, devMode);
            return new DeviceContext( hdc, DeviceContextType.NamedDevice ); 
        }

        /// 
        ///     CreateIC creates a DeviceContext object wrapping an hdc created with the Win32 CreateIC function. 
        /// 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static DeviceContext CreateIC(string driverName, string deviceName, string fileName, HandleRef devMode)
        { 
            // Note: All input params can be null but not at the same time.  See MSDN for information.

            IntPtr hdc = IntUnsafeNativeMethods.CreateIC(driverName, deviceName, fileName, devMode);
            return new DeviceContext( hdc, DeviceContextType.Information ); 
        }
 
        ///  
        ///     Creates a DeviceContext object wrapping a memory DC compatible with the specified device.
        ///  
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static DeviceContext FromCompatibleDC(IntPtr hdc)
        { 

 
            // If hdc is null, the function creates a memory DC compatible with the application's current screen. 
            // Win2K+: (See CreateCompatibleDC in the MSDN).
            // In this case the thread that calls CreateCompatibleDC owns the HDC that is created. When this thread is destroyed, 
            // the HDC is no longer valid.

            IntPtr compatibleDc = IntUnsafeNativeMethods.CreateCompatibleDC( new HandleRef(null, hdc) );
            return new DeviceContext(compatibleDc, DeviceContextType.Memory); 
        }
 
        ///  
        /// 
        ///     Used for wrapping an existing hdc.  In this case, this object doesn't own the hdc 
        ///     so calls to GetHdc/ReleaseHdc don't PInvoke into GDI.
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static DeviceContext FromHdc(IntPtr hdc)
        { 
            Debug.Assert( hdc != IntPtr.Zero, "hdc == 0" ); 
            return new DeviceContext(hdc, DeviceContextType.Unknown);
        } 

        /// 
        /// 
        ///     When hwnd is null, we are getting the screen DC. 
        /// 
        public static DeviceContext FromHwnd( IntPtr hwnd ) 
        { 
            return new DeviceContext(hwnd);
        } 


        /// 
        ~DeviceContext() 
        {
            Dispose(false); 
        } 

        ///  
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        ///  
        internal void Dispose(bool disposing)
        { 
            if (disposed)
            {
                return;
            } 

            if (this.Disposing != null) 
            { 
                this.Disposing(this, EventArgs.Empty);
            } 

            this.disposed = true;

#if !DRAWING_NAMESPACE 
            DisposeFont(disposing);
#endif 
 
            switch( this.dcType )
            { 
                case DeviceContextType.Display:
                    Debug.Assert( disposing, "WARNING: Finalizing a Display DeviceContext.\r\nReleaseDC may fail when not called from the same thread GetDC was called from." );

                    ((IDeviceContext)this).ReleaseHdc(); 
                    break;
 
                case DeviceContextType.Information: 
                case DeviceContextType.NamedDevice:
 
                    // CreateDC and CreateIC add an HDC handle to the HandleCollector; to remove it properly we need
                    // to call DeleteHDC.
#if TRACK_HDC
                    Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DC.DeleteHDC(hdc=0x{0:x8})", (int) this.hDC))); 
#endif
 
                    IntUnsafeNativeMethods.DeleteHDC(new HandleRef(this, this.hDC)); 

                    this.hDC = IntPtr.Zero; 
                    break;

                case DeviceContextType.Memory:
 
                    // CreatCompatibleDC adds a GDI handle to HandleCollector, to remove it properly we need to call
                    // DeleteDC. 
#if TRACK_HDC 
                    Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("DC.DeleteDC(hdc=0x{0:x8})", (int) this.hDC)));
#endif 
                    IntUnsafeNativeMethods.DeleteDC(new HandleRef(this, this.hDC));

                    this.hDC = IntPtr.Zero;
                    break; 

                // case DeviceContextType.Metafile: - not yet supported. 
#if [....]_PUBLIC_GRAPHICS_LIBRARY 
                case DeviceContextType.Metafile:
                    IntUnsafeNativeMethods.CloseEnhMetaFile(new HandleRef(this, this.Hdc)); 

                    this.hDC = IntPtr.Zero;
                    break;
#endif 
                case DeviceContextType.Unknown:
                default: 
                    return; 
                    // do nothing, the hdc is not owned by this object.
                    // in this case it is ok if disposed throught finalization. 
            }

            DbgUtil.AssertFinalization(this, disposing);
        } 

        ///  
        ///  
        ///     Explicit interface method implementation to hide them a bit for usability reasons so the object is seen
        ///     as a wrapper around an hdc that is always available, and for performance reasons since it caches the hdc 
        ///     if used in this way.
        /// 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        IntPtr IDeviceContext.GetHdc()
        { 
            if (this.hDC == IntPtr.Zero) 
            {
                Debug.Assert( this.dcType == DeviceContextType.Display, "Calling GetDC from a non display/window device." ); 

                // Note: for common DCs, GetDC assigns default attributes to the DC each time it is retrieved.
                // For example, the default font is System.
                this.hDC = IntUnsafeNativeMethods.GetDC(new HandleRef(this, this.hWnd)); 
#if TRACK_HDC
                Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("hdc[0x{0:x8}]=DC.GetHdc(hWnd=0x{1:x8})", (int) this.hDC, (int) this.hWnd))); 
#endif 
            }
 
            return this.hDC;
        }

 
        /// 
        /// 
        ///     If the object was created from a DC, this object doesn't 'own' the dc so we just ignore 
        ///     this call.
        /// 
        void IDeviceContext.ReleaseHdc()
        {
            if (this.hDC != IntPtr.Zero && this.dcType == DeviceContextType.Display)
            { 
#if TRACK_HDC
                int retVal = 
#endif 
                IntUnsafeNativeMethods.ReleaseDC(new HandleRef(this, this.hWnd), new HandleRef(this, this.hDC));
                // Note: retVal == 0 means it was not released but doesn't necessarily means an error; class or private DCs are never released. 
#if TRACK_HDC
                Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("[ret={0}]=DC.ReleaseDC(hDc=0x{1:x8}, hWnd=0x{2:x8})", retVal, (int) this.hDC, (int) this.hWnd)));
#endif
                this.hDC = IntPtr.Zero; 
            }
        } 
 

        ///  
        ///     Specifies whether the DC is in GM_ADVANCE mode (supported only in NT platforms).
        ///     If false, it is in GM_COMPATIBLE mode.
        /// 
        public DeviceContextGraphicsMode GraphicsMode 
        {
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get
            { 
                return (DeviceContextGraphicsMode) IntUnsafeNativeMethods.GetGraphicsMode( new HandleRef( this, this.Hdc ) );
            }
#if [....]_PUBLIC_GRAPHICS_LIBRARY
            set 
            {
                SetGraphicsMode(value); 
            } 
#endif
        } 

        /// 
        ///     Sets the dc graphics mode and returns the old value.
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public DeviceContextGraphicsMode SetGraphicsMode(DeviceContextGraphicsMode newMode) 
        {
            return (DeviceContextGraphicsMode) IntUnsafeNativeMethods.SetGraphicsMode( new HandleRef( this, this.Hdc ), (int) newMode ); 
        }

        /// 
        ///     Restores the device context to the specified state. The DC is restored by popping state information off a 
        ///     stack created by earlier calls to the SaveHdc function.
        ///     The stack can contain the state information for several instances of the DC. If the state specified by the 
        ///     specified parameter is not at the top of the stack, RestoreDC deletes all state information between the top 
        ///     of the stack and the specified instance.
        ///     Specifies the saved state to be restored. If this parameter is positive, nSavedDC represents a specific 
        ///     instance of the state to be restored. If this parameter is negative, nSavedDC represents an instance relative
        ///     to the current state. For example, -1 restores the most recently saved state.
        ///     See MSDN for more info.
        ///  
        public void RestoreHdc()
        { 
#if TRACK_HDC 
            bool result =
#endif 
            // Note: Don't use the Hdc property here, it would force handle creation.
            IntUnsafeNativeMethods.RestoreDC(new HandleRef(this, this.hDC), -1);
#if TRACK_HDC
            // Note: [....] may call this method during app exit at which point the DC may have been finalized already causing this assert to popup. 
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("ret[0]=DC.RestoreHdc(hDc=0x{1:x8}, state={2})", result, (int) this.hDC, restoreState) ));
#endif 
            Debug.Assert(contextStack != null, "Someone is calling RestoreHdc() before SaveHdc()"); 

            if (contextStack != null) { 
                GraphicsState g = (GraphicsState) contextStack.Pop();

                hCurrentBmp     = g.hBitmap;
                hCurrentBrush   = g.hBrush; 
                hCurrentPen     = g.hPen;
                hCurrentFont    = g.hFont; 
 
#if !DRAWING_NAMESPACE
                if (g.font != null && g.font.IsAlive) { 
                    selectedFont    = g.font.Target as WindowsFont;
                }
                else {
                    WindowsFont previousFont = selectedFont; 
                    selectedFont = null;
                    if (previousFont != null && MeasurementDCInfo.IsMeasurementDC(this)) { 
                        previousFont.Dispose(); 
                    }
                } 
#endif

            }
 
#if OPTIMIZED_MEASUREMENTDC
            // in this case, GDI will copy back the previously saved font into the DC. 
            // we dont actually know what the font is in our measurement DC so 
            // we need to clear it off.
            MeasurementDCInfo.ResetIfIsMeasurementDC(this.hDC); 
#endif

        }
 
        /// 
        ///     Saves the current state of the device context by copying data describing selected objects and graphic 
        ///     modes (such as the bitmap, brush, palette, font, pen, region, drawing mode, and mapping mode) to a 
        ///     context stack.
        ///     The SaveDC function can be used any number of times to save any number of instances of the DC state. 
        ///     A saved state can be restored by using the RestoreHdc method.
        ///     See MSDN for more details.
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public int SaveHdc() 
        { 
            HandleRef hdc = new HandleRef( this, this.Hdc);
            int state = IntUnsafeNativeMethods.SaveDC(hdc); 

            if (contextStack == null) {
                contextStack = new Stack();
            } 

            GraphicsState g = new GraphicsState(); 
            g.hBitmap = hCurrentBmp; 
            g.hBrush  = hCurrentBrush;
            g.hPen    = hCurrentPen; 
            g.hFont   = hCurrentFont;

#if !DRAWING_NAMESPACE
            g.font    = new WeakReference(selectedFont); 
#endif
 
 
            contextStack.Push(g);
 
#if TRACK_HDC
            Debug.WriteLine( DbgUtil.StackTraceToStr( String.Format("state[0]=DC.SaveHdc(hDc=0x{1:x8})", state, (int) this.hDC) ));
#endif
 
            return state;
        } 
 
        /// 
        ///     Selects a region as the current clipping region for the device context. 
        ///     Remarks (From MSDN):
        ///         - Only a copy of the selected region is used. The region itself can be selected for any number of other device contexts or it can be deleted.
        ///         - The SelectClipRgn function assumes that the coordinates for a region are specified in device units.
        ///         - To remove a device-context's clipping region, specify a NULL region handle. 
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public void SetClip(WindowsRegion region)
        { 
            HandleRef hdc = new HandleRef(this, this.Hdc);
            HandleRef hRegion = new HandleRef(region, region.HRegion);

            IntUnsafeNativeMethods.SelectClipRgn(hdc, hRegion); 
        }
 
        /// 
        ///     Creates a new clipping region from the intersection of the current clipping region and
        ///     the specified rectangle. 
        ///
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public void IntersectClip(WindowsRegion wr) 
        {
            //if the incoming windowsregion is infinite, there is no need to do any intersecting. 
            if (wr.HRegion == IntPtr.Zero) { 
                return;
            } 

            WindowsRegion clip = new WindowsRegion(0,0,0,0);
            try {
                 int result = IntUnsafeNativeMethods.GetClipRgn(new HandleRef( this, this.Hdc), new HandleRef(clip, clip.HRegion)); 

                 // If the function succeeds and there is a clipping region for the given device context, the return value is 1. 
                 if (result == 1) { 
                     Debug.Assert(clip.HRegion != IntPtr.Zero);
                     wr.CombineRegion(clip, wr, RegionCombineMode.AND); //1 = AND (or Intersect) 
                 }

                 SetClip(wr);
            } 
            finally {
                 clip.Dispose(); 
            } 
        }
 
        /// 
        ///     Modifies the viewport origin for a device context using the specified horizontal and vertical offsets in logical units.
        /// 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public void TranslateTransform(int dx, int dy) 
        { 
            IntNativeMethods.POINT orgn = new IntNativeMethods.POINT();
            IntUnsafeNativeMethods.OffsetViewportOrgEx( new HandleRef( this, this.Hdc ), dx, dy, orgn ); 
        }

        /// 
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
        public override bool Equals(object obj) 
        {
            DeviceContext other = obj as DeviceContext; 

            if (other == this)
            {
                return true; 
            }
 
            if (other == null) 
            {
                return false; 
            }

            // Note: Use property instead of field so the HDC is initialized.  Also, this avoid serialization issues (the obj could be a proxy that does not have access to private fields).
            return other.Hdc == this.Hdc; 
        }
 
        ///  
        ///     This allows collections to treat DeviceContext objects wrapping the same HDC as the same objects.
        ///  
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public override int GetHashCode()
        { 
            return this.Hdc.GetHashCode();
        } 
 

        internal class GraphicsState { 
            internal IntPtr hBrush;
            internal IntPtr hFont;
            internal IntPtr hPen;
            internal IntPtr hBitmap; 
#if !DRAWING_NAMESPACE
            internal WeakReference font; 
#endif 
        }
     } 
}

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