NET 中,使用 GDI 來精確測量文本的實際繪出尺寸(C#)

来源:互联网 发布:最新经典网络语言大全 编辑:程序博客网 时间:2024/04/25 17:05
NET 中,使用 GDI 來精確測量文本的實際繪出尺寸(C#)作者:未知日期:2004-10-12人氣:28投稿:snow(轉貼)來源:未知字體:大 中 小收藏:加入瀏覽器收藏  以下正文: 閱讀要求:瞭解 C# 調用 Win32API 的基本原理和操作方式 
-------------------------------------------------------------------------------- 


在開發 WinForm 控件時,通常需要測量文本繪出時的實際尺寸。 
.NET FCL 中的 GDI+ 類——System.Drawing.Graphics 提供了用於上述需要的 MeasureString 方法,該方法返回了一個 SizeF 結構的浮點數表示的結果,從表面上看起來似乎很精確,但在實際使用中發現有時此方法並不能精確測量出文本的實際寬度。 
也曾反編譯 System.Drawing.Dll,但沒看出什麼名堂來。 
如果使用 GDI 卻能很好地測量出文本的實際繪出寬度,下面提供了調用 GDI Win32API 來測量的 C# 實現源代碼,以供參考。 

註: 代碼中的 WindowsAPI 是一個自定義類,包裝了大部分 Win32API 調用的 C# 定義。 

/// <summary> 
/// 在指定的矩形區域內,按照指定的格式,測量文本的實際繪出尺寸。 
/// </summary> 
/// <param name="graphics">繪圖對像</param> 
/// <param name="text">被測量的文本</param> 
/// <param name="font">測量所用字體</param> 
/// <param name="rc">以矩形表示的要繪製區域</param> 
/// <param name="drawFlags">文本格式</param> 
/// <returns>尺寸</returns> 
public static Size GetTextSize(Graphics graphics, string text, Font font, Rectangle rc, DrawTextFormatFlags drawFlags) 

// 一個記錄設備上下文句柄的變量 
IntPtr hdc = IntPtr.Zero; 

if ( graphics != null ) 

// 獲取與提供的 Graphics 關聯的設備上下文句柄 
hdc = graphics.GetHdc(); 

else 

// 如果未提供 Graphics,使用屏幕作為設備上下文 
hdc = WindowsAPI.GetDC(IntPtr.Zero); 


// 測量所用字體的句柄 
IntPtr fontHandle = font.ToHfont(); 

// 將測量所用字體添加到設備上下文 
// 並記錄原來所使用的字體 
IntPtr oldHfont = WindowsAPI.SelectObject(hdc, fontHandle); 


// RECT 用於 Win32API 調用,.NET FCL 中的 Retangle 不適用於 Win32API 調用。 
// 其定義如下: 
// 
// [StructLayout(LayoutKind.Sequential)] // 這是必須的。 
// public struct RECT 
// { 
// public int left; 
// public int top; 
// public int right; 
// public int bottom; 
// } 


// 創建一個 GDI Win32API 調用所需的 RECT 實例 
RECT rect = new RECT(); 
rect.left = rc.Left; 
rect.right = rc.Right; 
rect.top = rc.Top; 
rect.bottom = rc.Bottom; 


// 文本繪製格式標誌的枚舉定義: 
// public enum DrawTextFormatFlags 
// { 
// DT_TOP = 0x00000000, 
// DT_LEFT = 0x00000000, 
// DT_CENTER = 0x00000001, 
// DT_RIGHT = 0x00000002, 
// DT_VCENTER = 0x00000004, 
// DT_BOTTOM = 0x00000008, 
// DT_WORDBREAK = 0x00000010, 
// DT_SINGLELINE = 0x00000020, 
// DT_EXPANDTABS = 0x00000040, 
// DT_TABSTOP = 0x00000080, 
// DT_NOCLIP = 0x00000100, 
// DT_EXTERNALLEADING = 0x00000200, 
// DT_CALCRECT = 0x00000400, 
// DT_NOPREFIX = 0x00000800, 
// DT_INTERNAL = 0x00001000, 
// DT_EDITCONTROL = 0x00002000, 
// DT_PATH_ELLIPSIS = 0x00004000, 
// DT_END_ELLIPSIS = 0x00008000, 
// DT_MODIFYSTRING = 0x00010000, 
// DT_RTLREADING = 0x00020000, 
// DT_WORD_ELLIPSIS = 0x00040000 
// } 

// 調用 GDI Win32API 以測量文本的實際繪出時尺寸。 
WindowsAPI.DrawText(hdc, text, text.Length, ref rect, 
(int)(drawFlags | DrawTextFormatFlags.DT_CALCRECT)); 

// 重設為原來的字體,這是 GDI 必須的。 
WindowsAPI.SelectObject(hdc, oldHfont); 

// 刪除創建的測量用字體的句柄 
WindowsAPI.DeleteObject(fontHandle); 

// 釋放已獲取的設備上下文句柄 
if ( graphics != null ) 
graphics.ReleaseHdc(hdc); 
else 
WindowsAPI.ReleaseDC(IntPtr.Zero, hdc); 

// 返回實測結果 
return new Size(rect.right - rect.left, rect.bottom - rect.top); 



以下是三個有用的重載方法: 

public static Size GetTextSize(string text, Font font, Rectangle rc, DrawTextFormatFlags drawFlags) 

return GetTextSize(null, text, font, rc, drawFlags); 


public static Size GetTextSize(Graphics graphics, string text, Font font) 

// 設置一個文本繪製格式,以單行左對齊方式來測量。 
DrawTextFormatFlags drawFlags = 
DrawTextFormatFlags.DT_SINGLELINE | 
DrawTextFormatFlags.DT_LEFT | 
DrawTextFormatFlags.DT_CALCRECT; // 這個標誌表示要測量 

Rectangle rect = Rectangle.Empty; 

return GetTextSize(graphics, text, font, rect, drawFlags) ; 


public static Size GetTextSize(string text, Font font) 

return GetTextSize(null, text, font); 
原创粉丝点击