/// <summary> /// 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. /// </summary> 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, _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, unchecked ((int)_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 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(_hDC); #endif }
/// <summary> /// 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. /// </summary> public int SaveHdc() { HandleRef hdc = new HandleRef(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; _contextStack.Push(g); #if TRACK_HDC Debug.WriteLine(DbgUtil.StackTraceToStr(string.Format("state[0]=DC.SaveHdc(hDc=0x{1:x8})", state, unchecked ((int)_hDC)))); #endif return(state); }
/// <include file='doc\IDeviceContext.uex' path='docs/doc[@for="DeviceContext.Dispose1"]/*' /> internal void Dispose(bool disposing) { if (_disposed) { return; } if (Disposing != null) { Disposing(this, EventArgs.Empty); } _disposed = true; switch (_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})", unchecked ((int)_hDC)))); #endif IntUnsafeNativeMethods.DeleteHDC(new HandleRef(this, _hDC)); _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})", unchecked ((int)_hDC)))); #endif IntUnsafeNativeMethods.DeleteDC(new HandleRef(this, _hDC)); _hDC = IntPtr.Zero; break; // case DeviceContextType.Metafile: - not yet supported. 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); }
/// <summary> /// Constructor to construct a DeviceContext object from an existing Win32 device context handle. /// </summary> private DeviceContext(IntPtr hDC, DeviceContextType dcType) { _hDC = hDC; _dcType = dcType; CacheInitialState(); DeviceContexts.AddDeviceContext(this); #if TRACK_HDC Debug.WriteLine(DbgUtil.StackTraceToStr($"DeviceContext(hDC=0x{(int)hDC:X8}, Type={dcType})")); #endif }
/// <summary> /// Constructor to construct a DeviceContext object from an window handle. /// </summary> private DeviceContext(IntPtr hWnd) { _hWnd = hWnd; _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} )", unchecked ((int)hWnd)))); #endif }
///<summary> /// If the object was created from a DC, this object doesn't 'own' the dc so we just ignore this call. ///</summary> void IDeviceContext.ReleaseHdc() { if (_hDC != IntPtr.Zero && _dcType == DeviceContextType.Display) { #if TRACK_HDC int retVal = #endif IntUnsafeNativeMethods.ReleaseDC(new HandleRef(this, _hWnd), new HandleRef(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, unchecked ((int)_hDC), unchecked ((int)_hWnd)))); #endif _hDC = IntPtr.Zero; } }
/// <summary> /// 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. /// </summary> IntPtr IDeviceContext.GetHdc() { if (_hDC == IntPtr.Zero) { Debug.Assert(_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. _hDC = IntUnsafeNativeMethods.GetDC(new HandleRef(this, _hWnd)); #if TRACK_HDC Debug.WriteLine(DbgUtil.StackTraceToStr(string.Format("hdc[0x{0:x8}]=DC.GetHdc(hWnd=0x{1:x8})", unchecked ((int)_hDC), unchecked ((int)_hWnd)))); #endif } return(_hDC); }
/// <summary> /// Constructor to construct a DeviceContext object from an existing Win32 device context handle. /// </summary> private DeviceContext(IntPtr hDC, DeviceContextType dcType) { _hDC = hDC; _dcType = dcType; CacheInitialState(); DeviceContexts.AddDeviceContext(this); if (dcType == DeviceContextType.Display) { _hWnd = IntUnsafeNativeMethods.WindowFromDC(new HandleRef(this, _hDC)); } #if TRACK_HDC Debug.WriteLine(DbgUtil.StackTraceToStr(string.Format("DeviceContext( hDC=0x{0:X8}, Type={1} )", unchecked ((int)hDC), dcType))); #endif }
/// <summary> /// Constructor to construct a DeviceContext object from an existing Win32 device context handle. /// </summary> private DeviceContext(IntPtr hDC, DeviceContextType dcType) { _hDC = hDC; _dcType = dcType; CacheInitialState(); DeviceContexts.AddDeviceContext(this); if (dcType == DeviceContextType.Display) { _hWnd = Interop.User32.WindowFromDC(new HandleRef(this, _hDC)); } #if TRACK_HDC Debug.WriteLine(DbgUtil.StackTraceToStr($"DeviceContext(hDC=0x{(int)hDC:X8}, Type={dcType})")); #endif }