GDI 透過 GetTextExtentPoint32 即可輕鬆測量文字尺寸,但 Direct2D 架構分離了字體(IDWriteTextFormat)與排版(IDWriteTextLayout),測量流程較為迂迴。本文詳解關鍵介面串聯流程,附完整代碼片段。
IDWriteFactory* pDWriteFactory = GetDirectWriteFactory(); // 單例取得
IDWriteTextFormat* pTextFormat = nullptr;
HRESULT hr = pDWriteFactory->CreateTextFormat(
L"Microsoft JhengHei", // 字型名稱
nullptr, // 字型集合(null 使用系統預設)
DWRITE_FONT_WEIGHT_NORMAL, // 粗細
DWRITE_FONT_STYLE_NORMAL, // 樣式
DWRITE_FONT_STRETCH_NORMAL, // 伸縮
16.0f, // 字體大小 (DIP)
L"", // 語系(空字串 = 使用者預設)
&pTextFormat
);
if (SUCCEEDED(hr)) {
pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); // 單行模式
}
IDWriteTextLayout* pTextLayout = nullptr;
const WCHAR* text = L"測試文字";
UINT32 length = wcslen(text);
hr = pDWriteFactory->CreateTextLayout(
text, length,
pTextFormat,
0.0f, 0.0f, // 排版寬高(0 = 無限制)
&pTextLayout
);
if (SUCCEEDED(hr)) {
DWRITE_TEXT_METRICS metrics;
hr = pTextLayout->GetMetrics(&metrics);
if (SUCCEEDED(hr)) {
// 關鍵尺寸:含尾隨空白寬度、高度
float width = ceilf(metrics.widthIncludingTrailingWhitespace);
float height = ceilf(metrics.height);
// 使用 width/height 進行佈局計算...
}
pTextLayout->Release();
}
| 欄位 | 含義 |
|---|---|
width | 不含尾隨空白的排版寬度 |
widthIncludingTrailingWhitespace | 含尾隨空白寬度(通常用於佈局) |
height | 排版高度(含行距) |
layoutWidth/Height | 建構時指定的最大排版框尺寸 |
maxBidiReorderingDepth | 雙向文字重排深度 |
TextLayout,再 TextFormat,最後 Factory(通常為單例不釋放)DPI/96TextLayout 可快取重用,避免重複建構掌握文字測量後,可構建類 WPF 的保留模式 GUI 框架:
文中截圖展示的 Win7 風格按鈕(含漸層、動畫、自動對齊),即由此佈局系統驅動,而非硬編碼座標。