Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Misc / GDI / WindowsFont.cs / 1 / WindowsFont.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- #if WINFORMS_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal #else namespace System.Experimental.Gdi #endif { using System; using System.Internal; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Text; using System.Security; using System.Security.Permissions; using System.Globalization; ////// #if WINFORMS_PUBLIC_GRAPHICS_LIBRARY public #else internal #endif sealed partial class WindowsFont : MarshalByRefObject, ICloneable, IDisposable { const int LogFontNameOffset = 28; // Handle to the native Windows font object. // private IntPtr hFont; private float fontSize = -1.0f; //invalid value. private int lineSpacing; private bool ownHandle; private bool ownedByCacheManager; private bool everOwnedByCacheManager; private IntNativeMethods.LOGFONT logFont; private FontStyle style; // Note: These defaults are according to the ones in GDI+ but those are not necessarily the same as the system // default font. The GetSystemDefaultHFont() method should be used if needed. private const string defaultFaceName = "Microsoft Sans Serif"; private const float defaultFontSize = 8.25f; private const int defaultFontHeight = 13; #if GDI_FINALIZATION_WATCH private string AllocationSite = DbgUtil.StackTrace; #endif ////// Encapsulates a GDI Font object. /// ////// Creates the font handle. /// private void CreateFont() { Debug.Assert( hFont == IntPtr.Zero, "hFont is not null, this will generate a handle leak." ); Debug.Assert( this.logFont != null, "WindowsFont.logFont not initialized." ); this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont))); #endif if (this.hFont == IntPtr.Zero) { this.logFont.lfFaceName = defaultFaceName; this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_ONLY_PRECIS; // True Type only. this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont))); #endif } // Update logFont height and other adjusted parameters. // IntUnsafeNativeMethods.GetObject(new HandleRef(this, this.hFont), this.logFont); // We created the hFont, we will delete it on dispose. this.ownHandle = true; } /// Constructors. ////// Contructor to construct font from a face name. /// > public WindowsFont( string faceName ) : this(faceName, defaultFontSize, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { // Default size in WinForms is 8.25f. } ////// Contructor to construct font from a face name, a desired size and with the specified style. /// > public WindowsFont( string faceName, float size ) : this(faceName, size, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { } ////// Contructor to construct font from a face name, a desired size and with the specified style. /// > public WindowsFont( string faceName, float size, FontStyle style ) : this(faceName, size, style, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { } ////// Contructor to construct font from a face name, a desired size in points and with the specified style /// and character set. The screen dc is used for calculating the font em height. /// > public WindowsFont( string faceName, float size, FontStyle style, byte charSet, WindowsFontQuality fontQuality ) { Debug.Assert( size > 0.0f, "size has a negative value." ); const byte True = 1; const byte False = 0; this.logFont = new IntNativeMethods.LOGFONT(); // // Get the font height from the specified size. size is in point units and height in logical // units (pixels when using MM_TEXT) so we need to make the conversion using the number of // pixels per logical inch along the screen height. // int pixelsY = (int) Math.Ceiling( WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.DpiY * size / 72); // 1 point = 1/72 inch.; // // The lfHeight represents the font cell height (line spacing) which includes the internal // leading; we specify a negative size value (in pixels) for the height so the font mapper // provides the closest match for the character height rather than the cell height (MSDN). // this.logFont.lfHeight = -pixelsY; this.logFont.lfFaceName = faceName != null ? faceName : defaultFaceName; this.logFont.lfCharSet = charSet; this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_PRECIS; this.logFont.lfQuality = (byte) fontQuality; this.logFont.lfWeight = (style & FontStyle.Bold) == FontStyle.Bold ? IntNativeMethods.FW_BOLD : IntNativeMethods.FW_NORMAL; this.logFont.lfItalic = (style & FontStyle.Italic) == FontStyle.Italic ? True : False; this.logFont.lfUnderline = (style & FontStyle.Underline) == FontStyle.Underline ? True : False; this.logFont.lfStrikeOut = (style & FontStyle.Strikeout) == FontStyle.Strikeout ? True : False; // Let the Size be recomputed to be consistent with the Height (there may be some precision loss coming from size to height). // this.fontSize = size; this.style = style; CreateFont(); } ////// Contructor to construct font from a LOGFONT structure. /// Pass false in the createHandle param to create a 'compatible' font (handle-less, to be used for measuring/comparing) or /// when the handle has already been created. /// private WindowsFont( IntNativeMethods.LOGFONT lf, bool createHandle ) { Debug.Assert( lf != null, "lf is null" ); this.logFont = lf; if (this.logFont.lfFaceName == null) { this.logFont.lfFaceName = defaultFaceName; } this.style = FontStyle.Regular; if (lf.lfWeight == IntNativeMethods.FW_BOLD) { this.style |= FontStyle.Bold; } if (lf.lfItalic == 1) { this.style |= FontStyle.Italic; } if (lf.lfUnderline == 1) { this.style |= FontStyle.Underline; } if (lf.lfStrikeOut == 1) { this.style |= FontStyle.Strikeout; } if( createHandle ) { CreateFont(); } } ////// Contructs a WindowsFont object from an existing System.Drawing.Font object (GDI+), based on the screen dc MapMode /// and resolution (normally: MM_TEXT and 96 dpi). /// public static WindowsFont FromFont(Font font) { return FromFont(font, WindowsFontQuality.Default); } public static WindowsFont FromFont(Font font, WindowsFontQuality fontQuality) { string familyName = font.FontFamily.Name; // Strip vertical-font mark from the name if needed. if (familyName != null && familyName.Length > 1 && familyName[0] == '@') { familyName = familyName.Substring(1); } // Note: Creating the WindowsFont from Font using a LOGFONT structure from GDI+ (Font.ToLogFont(logFont)) may sound like // a better choice (more accurate) for doing this but tests show that is not the case (see WindowsFontTests test suite), // the results are the same. Also, that approach has some issues when the Font is created in a different application // domain since the LOGFONT cannot be marshalled properly, see VSW#451960. // Now, creating it using the Font.SizeInPoints makes it GraphicsUnit-independent. return new WindowsFont(familyName, font.SizeInPoints, font.Style, font.GdiCharSet, fontQuality); } ////// Creates a WindowsFont from the font selected in the supplied dc. /// public static WindowsFont FromHdc( IntPtr hdc ) { IntPtr hFont = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(null, hdc), IntNativeMethods.OBJ_FONT); // don't call DeleteObject on handle from GetCurrentObject, it is the one selected in the hdc. return FromHfont( hFont ); } ////// Creates a WindowsFont from the handle to a native GDI font. It does not take ownership of the /// passed-in handle, the caller needs to delete the hFont when done with the WindowsFont. /// public static WindowsFont FromHfont( IntPtr hFont ) { return FromHfont( hFont, false ); } ////// Creates a WindowsFont from the handle to a native GDI font and optionally takes ownership of managing /// the lifetime of the handle. /// public static WindowsFont FromHfont( IntPtr hFont, bool takeOwnership ) { IntNativeMethods.LOGFONT lf = new IntNativeMethods.LOGFONT(); IntUnsafeNativeMethods.GetObject(new HandleRef(null, hFont), lf); WindowsFont wf = new WindowsFont( lf, /*createHandle*/ false ); wf.hFont = hFont; wf.ownHandle = takeOwnership; // if true, hFont will be deleted on dispose. return wf; } ~WindowsFont() { Dispose(false); } public void Dispose() { Dispose(true); } internal void Dispose(bool disposing) { bool deletedHandle = false; if (this.ownHandle) { if (!ownedByCacheManager || !disposing) { // If we were ever owned by the CacheManger and we're being disposed // we can be sure that we're not in use by any DC's (otherwise Dispose() wouldn't have been called) // skip the check IsFontInUse check in this case. // Also skip the check if disposing == false, because the cache is thread-static // and that means we're being called from the finalizer. if (everOwnedByCacheManager || !disposing || !DeviceContexts.IsFontInUse(this)) { Debug.Assert( this.hFont != IntPtr.Zero, "Unexpected null hFont." ); DbgUtil.AssertFinalization(this, disposing); IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, this.hFont)); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeleteObject(HFONT[0x{0:x8}]))", (int) this.hFont))); #endif this.hFont = IntPtr.Zero; this.ownHandle = false; deletedHandle = true; } } } if (disposing && (deletedHandle || !ownHandle)) { GC.SuppressFinalize(this); } } ////// Returns a value indicating whether the specified object is a WindowsFont equivalent to this object. /// public override bool Equals( object font ) { WindowsFont winFont = font as WindowsFont; if( winFont == null ) { return false; } if( winFont == this ) { return true; } // WARNING: don't use non-public fields/properties here, the passed-in font object could be a proxy in a // remoting scenario and proxies cannot access internal or private members. VSW#465265 & 465647 // Compare params used to create the font. return this.Name == winFont.Name && this.LogFontHeight == winFont.LogFontHeight && // Equivalent to comparing Size but always at hand. this.Style == winFont.Style && this.CharSet == winFont.CharSet && this.Quality == winFont.Quality; } ////// Gets the hash code for this WindowsFont. /// public override int GetHashCode() { // similar to Font.GetHashCode(). return (int)((((UInt32)this.Style << 13) | ((UInt32)this.Style >> 19)) ^ (((UInt32)this.CharSet << 26) | ((UInt32)this.CharSet >> 6)) ^ (((UInt32)this.Size << 7) | ((UInt32)this.Size >> 25))); } ////// Clones this object. /// public object Clone() { return new WindowsFont( this.logFont, true ); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "[{0}: Name={1}, Size={2} points, Height={3} pixels, Sytle={4}]", GetType().Name, logFont.lfFaceName, this.Size, this.Height, this.Style); } //////////////////////////////////////////// /// Properties ////// Returns this object's native Win32 font handle. Should NOT be deleted externally. /// Compare with ToHfont method. /// public IntPtr Hfont { get { //Assert removed. We need to be able to check for Hfont == IntPtr.Zero to determine if the object was disposed. //Debug.Assert(this.hFont != IntPtr.Zero, "hFont is null, are you using a disposed object?"); return this.hFont; } } ////// Determines whether the font has the italic style or not. /// public bool Italic { get { return logFont.lfItalic == 1; } } public bool OwnedByCacheManager { get { return ownedByCacheManager; } set { if (value) { everOwnedByCacheManager = true; } ownedByCacheManager = value; } } ////// Rendering quality. /// public WindowsFontQuality Quality { get { return (WindowsFontQuality) this.logFont.lfQuality; } } ////// Gets the font style. /// public FontStyle Style { get { return this.style; } } ////// Gets the line spacing (cell height) of this font in (screen) pixels using the screen resolution. /// Gets the line spacing (cell height), in pixels (using the screen DC resolution), of this font. /// The line spacing is the vertical distance between the base lines of two consecutive lines of text. /// Thus, the line spacing includes the blank space between lines along with the height of the character /// itself. /// public int Height { // get { if( this.lineSpacing == 0 ) { // Observe that the font text metrics are obtained using the resolution of the screen. WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics; // No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics // in WindowsGraphics methods. wg.DeviceContext.SelectFont(this); IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics(); this.lineSpacing = tm.tmHeight; } return this.lineSpacing; } } ////// Gets the font character set. /// This is used by the system font mapper when searching for the physical font that best matches the logical font. /// public byte CharSet { get { return logFont.lfCharSet; } } ////// Specifies the height, in logical units, of the font's character cell or character. The character height value (em height) /// is the character cell height value minus the internal-leading value. /// public int LogFontHeight { get { return logFont.lfHeight; } } ////// The font's face name. /// public string Name { get { return logFont.lfFaceName; } } ////// Gets the character height (as opposed to the cell height) of the font represented by this object in points. /// Consider /// public float Size { get { if( this.fontSize < 0.0f ) { WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics; // No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics // in WindowsGraphics methods. wg.DeviceContext.SelectFont(this); IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics(); // // Convert the font character height to points. If lfHeight is negative, Windows // treats the absolute value of that number as a desired font height compatible with // the point size; in this case lfHeight will roughly match the tmHeight field of // the TEXTMETRIC structure less the tmInternalLeading field. // int height = this.logFont.lfHeight > 0 ? tm.tmHeight : (tm.tmHeight - tm.tmInternalLeading); // /* switch (this.unit) { case GraphicsUnit.Pixel: worldEmSize = height * dpi / 72.0f; break; case GraphicsUnit.Point: worldEmSize = height * dpi / 72.0f; break; case GraphicsUnit.Inch: worldEmSize = height * dpi; break; case GraphicsUnit.Document: worldEmSize = height * dpi / 300.0f; break; case GraphicsUnit.Millimeter: worldEmSize = height * dpi / 25.4f; break; } */ this.fontSize = height * 72f / wg.DeviceContext.DpiY; } return this.fontSize; } } ////// Attempts to match the TextRenderingHint of the specified Graphics object with a LOGFONT.lfQuality value. /// public static WindowsFontQuality WindowsFontQualityFromTextRenderingHint(Graphics g) { if (g == null) { return WindowsFontQuality.Default; } switch (g.TextRenderingHint) { case TextRenderingHint.ClearTypeGridFit: // See WindowsFontQuality enum for the flags supported in the different OS systems. if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) { return WindowsFontQuality.ClearTypeNatural; } else { return WindowsFontQuality.ClearType; } case TextRenderingHint.AntiAliasGridFit: return WindowsFontQuality.AntiAliased; case TextRenderingHint.AntiAlias: return WindowsFontQuality.AntiAliased; case TextRenderingHint.SingleBitPerPixelGridFit: return WindowsFontQuality.Proof; case TextRenderingHint.SingleBitPerPixel: return WindowsFontQuality.Draft; default: case TextRenderingHint.SystemDefault: return WindowsFontQuality.Default; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- #if WINFORMS_NAMESPACE namespace System.Windows.Forms.Internal #elif DRAWING_NAMESPACE namespace System.Drawing.Internal #else namespace System.Experimental.Gdi #endif { using System; using System.Internal; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Text; using System.Security; using System.Security.Permissions; using System.Globalization; ////// #if WINFORMS_PUBLIC_GRAPHICS_LIBRARY public #else internal #endif sealed partial class WindowsFont : MarshalByRefObject, ICloneable, IDisposable { const int LogFontNameOffset = 28; // Handle to the native Windows font object. // private IntPtr hFont; private float fontSize = -1.0f; //invalid value. private int lineSpacing; private bool ownHandle; private bool ownedByCacheManager; private bool everOwnedByCacheManager; private IntNativeMethods.LOGFONT logFont; private FontStyle style; // Note: These defaults are according to the ones in GDI+ but those are not necessarily the same as the system // default font. The GetSystemDefaultHFont() method should be used if needed. private const string defaultFaceName = "Microsoft Sans Serif"; private const float defaultFontSize = 8.25f; private const int defaultFontHeight = 13; #if GDI_FINALIZATION_WATCH private string AllocationSite = DbgUtil.StackTrace; #endif ////// Encapsulates a GDI Font object. /// ////// Creates the font handle. /// private void CreateFont() { Debug.Assert( hFont == IntPtr.Zero, "hFont is not null, this will generate a handle leak." ); Debug.Assert( this.logFont != null, "WindowsFont.logFont not initialized." ); this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont))); #endif if (this.hFont == IntPtr.Zero) { this.logFont.lfFaceName = defaultFaceName; this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_ONLY_PRECIS; // True Type only. this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont))); #endif } // Update logFont height and other adjusted parameters. // IntUnsafeNativeMethods.GetObject(new HandleRef(this, this.hFont), this.logFont); // We created the hFont, we will delete it on dispose. this.ownHandle = true; } /// Constructors. ////// Contructor to construct font from a face name. /// > public WindowsFont( string faceName ) : this(faceName, defaultFontSize, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { // Default size in WinForms is 8.25f. } ////// Contructor to construct font from a face name, a desired size and with the specified style. /// > public WindowsFont( string faceName, float size ) : this(faceName, size, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { } ////// Contructor to construct font from a face name, a desired size and with the specified style. /// > public WindowsFont( string faceName, float size, FontStyle style ) : this(faceName, size, style, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default) { } ////// Contructor to construct font from a face name, a desired size in points and with the specified style /// and character set. The screen dc is used for calculating the font em height. /// > public WindowsFont( string faceName, float size, FontStyle style, byte charSet, WindowsFontQuality fontQuality ) { Debug.Assert( size > 0.0f, "size has a negative value." ); const byte True = 1; const byte False = 0; this.logFont = new IntNativeMethods.LOGFONT(); // // Get the font height from the specified size. size is in point units and height in logical // units (pixels when using MM_TEXT) so we need to make the conversion using the number of // pixels per logical inch along the screen height. // int pixelsY = (int) Math.Ceiling( WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.DpiY * size / 72); // 1 point = 1/72 inch.; // // The lfHeight represents the font cell height (line spacing) which includes the internal // leading; we specify a negative size value (in pixels) for the height so the font mapper // provides the closest match for the character height rather than the cell height (MSDN). // this.logFont.lfHeight = -pixelsY; this.logFont.lfFaceName = faceName != null ? faceName : defaultFaceName; this.logFont.lfCharSet = charSet; this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_PRECIS; this.logFont.lfQuality = (byte) fontQuality; this.logFont.lfWeight = (style & FontStyle.Bold) == FontStyle.Bold ? IntNativeMethods.FW_BOLD : IntNativeMethods.FW_NORMAL; this.logFont.lfItalic = (style & FontStyle.Italic) == FontStyle.Italic ? True : False; this.logFont.lfUnderline = (style & FontStyle.Underline) == FontStyle.Underline ? True : False; this.logFont.lfStrikeOut = (style & FontStyle.Strikeout) == FontStyle.Strikeout ? True : False; // Let the Size be recomputed to be consistent with the Height (there may be some precision loss coming from size to height). // this.fontSize = size; this.style = style; CreateFont(); } ////// Contructor to construct font from a LOGFONT structure. /// Pass false in the createHandle param to create a 'compatible' font (handle-less, to be used for measuring/comparing) or /// when the handle has already been created. /// private WindowsFont( IntNativeMethods.LOGFONT lf, bool createHandle ) { Debug.Assert( lf != null, "lf is null" ); this.logFont = lf; if (this.logFont.lfFaceName == null) { this.logFont.lfFaceName = defaultFaceName; } this.style = FontStyle.Regular; if (lf.lfWeight == IntNativeMethods.FW_BOLD) { this.style |= FontStyle.Bold; } if (lf.lfItalic == 1) { this.style |= FontStyle.Italic; } if (lf.lfUnderline == 1) { this.style |= FontStyle.Underline; } if (lf.lfStrikeOut == 1) { this.style |= FontStyle.Strikeout; } if( createHandle ) { CreateFont(); } } ////// Contructs a WindowsFont object from an existing System.Drawing.Font object (GDI+), based on the screen dc MapMode /// and resolution (normally: MM_TEXT and 96 dpi). /// public static WindowsFont FromFont(Font font) { return FromFont(font, WindowsFontQuality.Default); } public static WindowsFont FromFont(Font font, WindowsFontQuality fontQuality) { string familyName = font.FontFamily.Name; // Strip vertical-font mark from the name if needed. if (familyName != null && familyName.Length > 1 && familyName[0] == '@') { familyName = familyName.Substring(1); } // Note: Creating the WindowsFont from Font using a LOGFONT structure from GDI+ (Font.ToLogFont(logFont)) may sound like // a better choice (more accurate) for doing this but tests show that is not the case (see WindowsFontTests test suite), // the results are the same. Also, that approach has some issues when the Font is created in a different application // domain since the LOGFONT cannot be marshalled properly, see VSW#451960. // Now, creating it using the Font.SizeInPoints makes it GraphicsUnit-independent. return new WindowsFont(familyName, font.SizeInPoints, font.Style, font.GdiCharSet, fontQuality); } ////// Creates a WindowsFont from the font selected in the supplied dc. /// public static WindowsFont FromHdc( IntPtr hdc ) { IntPtr hFont = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(null, hdc), IntNativeMethods.OBJ_FONT); // don't call DeleteObject on handle from GetCurrentObject, it is the one selected in the hdc. return FromHfont( hFont ); } ////// Creates a WindowsFont from the handle to a native GDI font. It does not take ownership of the /// passed-in handle, the caller needs to delete the hFont when done with the WindowsFont. /// public static WindowsFont FromHfont( IntPtr hFont ) { return FromHfont( hFont, false ); } ////// Creates a WindowsFont from the handle to a native GDI font and optionally takes ownership of managing /// the lifetime of the handle. /// public static WindowsFont FromHfont( IntPtr hFont, bool takeOwnership ) { IntNativeMethods.LOGFONT lf = new IntNativeMethods.LOGFONT(); IntUnsafeNativeMethods.GetObject(new HandleRef(null, hFont), lf); WindowsFont wf = new WindowsFont( lf, /*createHandle*/ false ); wf.hFont = hFont; wf.ownHandle = takeOwnership; // if true, hFont will be deleted on dispose. return wf; } ~WindowsFont() { Dispose(false); } public void Dispose() { Dispose(true); } internal void Dispose(bool disposing) { bool deletedHandle = false; if (this.ownHandle) { if (!ownedByCacheManager || !disposing) { // If we were ever owned by the CacheManger and we're being disposed // we can be sure that we're not in use by any DC's (otherwise Dispose() wouldn't have been called) // skip the check IsFontInUse check in this case. // Also skip the check if disposing == false, because the cache is thread-static // and that means we're being called from the finalizer. if (everOwnedByCacheManager || !disposing || !DeviceContexts.IsFontInUse(this)) { Debug.Assert( this.hFont != IntPtr.Zero, "Unexpected null hFont." ); DbgUtil.AssertFinalization(this, disposing); IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, this.hFont)); #if TRACK_HFONT Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeleteObject(HFONT[0x{0:x8}]))", (int) this.hFont))); #endif this.hFont = IntPtr.Zero; this.ownHandle = false; deletedHandle = true; } } } if (disposing && (deletedHandle || !ownHandle)) { GC.SuppressFinalize(this); } } ////// Returns a value indicating whether the specified object is a WindowsFont equivalent to this object. /// public override bool Equals( object font ) { WindowsFont winFont = font as WindowsFont; if( winFont == null ) { return false; } if( winFont == this ) { return true; } // WARNING: don't use non-public fields/properties here, the passed-in font object could be a proxy in a // remoting scenario and proxies cannot access internal or private members. VSW#465265 & 465647 // Compare params used to create the font. return this.Name == winFont.Name && this.LogFontHeight == winFont.LogFontHeight && // Equivalent to comparing Size but always at hand. this.Style == winFont.Style && this.CharSet == winFont.CharSet && this.Quality == winFont.Quality; } ////// Gets the hash code for this WindowsFont. /// public override int GetHashCode() { // similar to Font.GetHashCode(). return (int)((((UInt32)this.Style << 13) | ((UInt32)this.Style >> 19)) ^ (((UInt32)this.CharSet << 26) | ((UInt32)this.CharSet >> 6)) ^ (((UInt32)this.Size << 7) | ((UInt32)this.Size >> 25))); } ////// Clones this object. /// public object Clone() { return new WindowsFont( this.logFont, true ); } public override string ToString() { return string.Format(CultureInfo.CurrentCulture, "[{0}: Name={1}, Size={2} points, Height={3} pixels, Sytle={4}]", GetType().Name, logFont.lfFaceName, this.Size, this.Height, this.Style); } //////////////////////////////////////////// /// Properties ////// Returns this object's native Win32 font handle. Should NOT be deleted externally. /// Compare with ToHfont method. /// public IntPtr Hfont { get { //Assert removed. We need to be able to check for Hfont == IntPtr.Zero to determine if the object was disposed. //Debug.Assert(this.hFont != IntPtr.Zero, "hFont is null, are you using a disposed object?"); return this.hFont; } } ////// Determines whether the font has the italic style or not. /// public bool Italic { get { return logFont.lfItalic == 1; } } public bool OwnedByCacheManager { get { return ownedByCacheManager; } set { if (value) { everOwnedByCacheManager = true; } ownedByCacheManager = value; } } ////// Rendering quality. /// public WindowsFontQuality Quality { get { return (WindowsFontQuality) this.logFont.lfQuality; } } ////// Gets the font style. /// public FontStyle Style { get { return this.style; } } ////// Gets the line spacing (cell height) of this font in (screen) pixels using the screen resolution. /// Gets the line spacing (cell height), in pixels (using the screen DC resolution), of this font. /// The line spacing is the vertical distance between the base lines of two consecutive lines of text. /// Thus, the line spacing includes the blank space between lines along with the height of the character /// itself. /// public int Height { // get { if( this.lineSpacing == 0 ) { // Observe that the font text metrics are obtained using the resolution of the screen. WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics; // No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics // in WindowsGraphics methods. wg.DeviceContext.SelectFont(this); IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics(); this.lineSpacing = tm.tmHeight; } return this.lineSpacing; } } ////// Gets the font character set. /// This is used by the system font mapper when searching for the physical font that best matches the logical font. /// public byte CharSet { get { return logFont.lfCharSet; } } ////// Specifies the height, in logical units, of the font's character cell or character. The character height value (em height) /// is the character cell height value minus the internal-leading value. /// public int LogFontHeight { get { return logFont.lfHeight; } } ////// The font's face name. /// public string Name { get { return logFont.lfFaceName; } } ////// Gets the character height (as opposed to the cell height) of the font represented by this object in points. /// Consider /// public float Size { get { if( this.fontSize < 0.0f ) { WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics; // No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics // in WindowsGraphics methods. wg.DeviceContext.SelectFont(this); IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics(); // // Convert the font character height to points. If lfHeight is negative, Windows // treats the absolute value of that number as a desired font height compatible with // the point size; in this case lfHeight will roughly match the tmHeight field of // the TEXTMETRIC structure less the tmInternalLeading field. // int height = this.logFont.lfHeight > 0 ? tm.tmHeight : (tm.tmHeight - tm.tmInternalLeading); // /* switch (this.unit) { case GraphicsUnit.Pixel: worldEmSize = height * dpi / 72.0f; break; case GraphicsUnit.Point: worldEmSize = height * dpi / 72.0f; break; case GraphicsUnit.Inch: worldEmSize = height * dpi; break; case GraphicsUnit.Document: worldEmSize = height * dpi / 300.0f; break; case GraphicsUnit.Millimeter: worldEmSize = height * dpi / 25.4f; break; } */ this.fontSize = height * 72f / wg.DeviceContext.DpiY; } return this.fontSize; } } ////// Attempts to match the TextRenderingHint of the specified Graphics object with a LOGFONT.lfQuality value. /// public static WindowsFontQuality WindowsFontQualityFromTextRenderingHint(Graphics g) { if (g == null) { return WindowsFontQuality.Default; } switch (g.TextRenderingHint) { case TextRenderingHint.ClearTypeGridFit: // See WindowsFontQuality enum for the flags supported in the different OS systems. if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) { return WindowsFontQuality.ClearTypeNatural; } else { return WindowsFontQuality.ClearType; } case TextRenderingHint.AntiAliasGridFit: return WindowsFontQuality.AntiAliased; case TextRenderingHint.AntiAlias: return WindowsFontQuality.AntiAliased; case TextRenderingHint.SingleBitPerPixelGridFit: return WindowsFontQuality.Proof; case TextRenderingHint.SingleBitPerPixel: return WindowsFontQuality.Draft; default: case TextRenderingHint.SystemDefault: return WindowsFontQuality.Default; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- IPGlobalProperties.cs
- _AuthenticationState.cs
- XmlWriter.cs
- DateRangeEvent.cs
- InstallerTypeAttribute.cs
- Environment.cs
- DirectoryObjectSecurity.cs
- TextBreakpoint.cs
- ImageButton.cs
- TransformationRules.cs
- arc.cs
- ComboBoxRenderer.cs
- ObjectHelper.cs
- Types.cs
- GridViewRowPresenter.cs
- Point4D.cs
- ArrangedElement.cs
- ExternalException.cs
- SettingsPropertyNotFoundException.cs
- ClientEventManager.cs
- CompositeControl.cs
- Rectangle.cs
- TableRow.cs
- Menu.cs
- AutomationAttributeInfo.cs
- RowsCopiedEventArgs.cs
- AttributeProviderAttribute.cs
- RIPEMD160.cs
- SqlSelectStatement.cs
- CatalogPartCollection.cs
- glyphs.cs
- CodeIndexerExpression.cs
- TextBox.cs
- ZoneMembershipCondition.cs
- ResolveMatchesCD1.cs
- LineUtil.cs
- StateManager.cs
- DataBinding.cs
- Trace.cs
- MergePropertyDescriptor.cs
- QuaternionValueSerializer.cs
- safesecurityhelperavalon.cs
- CatalogZoneBase.cs
- DefaultWorkflowSchedulerService.cs
- ScriptManagerProxy.cs
- DataTableExtensions.cs
- PageEventArgs.cs
- Partitioner.cs
- DataMemberConverter.cs
- OdbcConnectionPoolProviderInfo.cs
- FrameworkContentElement.cs
- BitmapEffectOutputConnector.cs
- NativeBuffer.cs
- PtsHost.cs
- DynamicILGenerator.cs
- MaskedTextBox.cs
- prompt.cs
- MaterialGroup.cs
- _KerberosClient.cs
- AdornerDecorator.cs
- ExpressionBuilderCollection.cs
- WindowsTokenRoleProvider.cs
- XmlSchemaAnyAttribute.cs
- ParameterCollection.cs
- ConfigsHelper.cs
- ExponentialEase.cs
- Token.cs
- MissingFieldException.cs
- AsyncCompletedEventArgs.cs
- ContractDescription.cs
- AutomationTextAttribute.cs
- ResXBuildProvider.cs
- HandlerFactoryWrapper.cs
- PeerNameResolver.cs
- RegexCompiler.cs
- ItemCollection.cs
- recordstatefactory.cs
- Wizard.cs
- DirectoryRootQuery.cs
- cookieexception.cs
- WpfGeneratedKnownProperties.cs
- CompatibleIComparer.cs
- DataSourceProvider.cs
- ADMembershipProvider.cs
- BitmapPalettes.cs
- DoubleCollectionConverter.cs
- TraceSection.cs
- DataPagerFieldItem.cs
- IndexObject.cs
- XmlDataProvider.cs
- ADMembershipProvider.cs
- AccessorTable.cs
- ImageBrush.cs
- ClientEndpointLoader.cs
- HandlerWithFactory.cs
- StateWorkerRequest.cs
- HashMembershipCondition.cs
- HttpEncoder.cs
- SubstitutionList.cs
- ToolStripItemDesigner.cs