DeviceContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Misc / GDI / DeviceContext.cs / 3 / DeviceContext.cs

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

//#define TRACK_HDC 
//#define GDI_FINALIZATION_WATCH 

#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.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;
 
    /// 
    /// 
    ///     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 WINFORMS_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 WinForms,
        ///     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 sync.  DeviceContext needs to support these kind of properties to
        ///     be able to keep the GDI+ and GDI HDCs in sync.
        ///
        ///     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; 

        // 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 
        {
            get 
            {
                if( this.hDC == IntPtr.Zero )
                {
                    if( this.dcType == DeviceContextType.Display ) 
                    {
                        // 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.
 
        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);
        }
 
        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.
        ///  
        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. 
        /// 
        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. 
        ///  
        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.
        ///  
        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.
        ///  
        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 (this.hDC == IntPtr.Zero) // already disposed or HDC not allocated. 
            { 
                return;
            } 

#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 WINFORMS_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.
        ///  
        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 
        {
            get
            {
                return (DeviceContextGraphicsMode) IntUnsafeNativeMethods.GetGraphicsMode( new HandleRef( this, this.Hdc ) ); 
            }
#if WINFORMS_PUBLIC_GRAPHICS_LIBRARY 
            set 
            {
                SetGraphicsMode(value); 
            }
#endif
        }
 
        /// 
        ///     Sets the dc graphics mode and returns the old value. 
        ///  
        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: Winforms 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.
        ///  
        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.
        ///  
        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. 
        /// 
        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. 
        ///  
        public void TranslateTransform(int dx, int dy)
        { 
            IntNativeMethods.POINT orgn = new IntNativeMethods.POINT();
            IntUnsafeNativeMethods.OffsetViewportOrgEx( new HandleRef( this, this.Hdc ), dx, dy, orgn );
        }
 
        /// 
        ///  
        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.
        ///  
        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.
                        

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