標籤:ceil 格式化 virt 實現 寬度 換行 height 排版 white
轉載請註明出處:http://www.cnblogs.com/Ray1024
一、概述
最近在使用Direct2D和DirectWrite寫引擎,在引擎中需要實現文字標籤控制項。但是文字標籤的尺寸最好不是由我們人為指定的,要不然的話就會出現標籤中文本溢出、空白存留等等問題,這樣很影響美觀。這就需要我們在文字標籤的建立時根據文本的字型格式、文字排版等等因素來確定標籤大小,而不是人為地指定大小,即實現標籤大小的自適應功能(根據文本的內容、字型、格式等等因素得出的寬高來設定標籤的大小)。
然而,想要實現標籤大小的自適應功能,就需要測量Direct2D文本的大小。但是,如何測量Direct2D文字的大小呢,我在Direct2D中找了很久也沒有找到合適的方法,在搜尋引擎中也沒有找到理想的解決方案。最後,在DirectWrite的MSDN文檔中找到瞭解決方法。
這篇文章就來介紹一下怎樣使用DirectWrite來測量Direct2D文本的大小。
二、解決方案
以下是我實現的一段用於測量文本寬高尺寸的函數,先貼代碼:
// 使用IDWriteTextLayout擷取文字大小 HRESULT GetTextSize(const WCHAR* text, IDWriteTextFormat* pTextFormat, D2D1_SIZE_F& size) { HRESULT hr = S_OK; IDWriteTextLayout* pTextLayout = NULL; // 建立文本布局 hr = m_pDWriteFactory->CreateTextLayout(text, wcslen(text), pTextFormat, 0.0f, 0.0f, &pTextLayout); if (SUCCEEDED(hr)) { // 擷取文本尺寸 DWRITE_TEXT_METRICS textMetrics; hr = pTextLayout->GetMetrics(&textMetrics); size = D2D1::SizeF(ceil(textMetrics.widthIncludingTrailingWhitespace), ceil(textMetrics.height)); } SafeRelease(&pTextLayout); return hr; }
如上代碼中,測量文本尺寸過程如下:
1. 使用文本和字型建立IDWriteTextLayout對象
2. 從建立成功的IDWriteTextLayout對象中擷取文字大小資訊DWRITE_TEXT_METRICS結構體
3. 將文本資訊結構體中的文本尺寸放到參數的size中,用於返迴文本尺寸
三、深入解析
上面測量文字大小的代碼中,關鍵的工具就是DirectWrite中的IDWriteTextLayout介面。IDWriteTextLayout介面表示經過完全分析和格式化後的文字區塊,簡單地說就是一個布局後的文本。這個介面中有一個成員函數IDWriteTextLayout::GetMetrics(),我們需要的文字大小資訊就可以通過這個函數來擷取。重點介紹一下這個函數:
IDWriteTextLayout::GetMetrics 方法介紹 功能 檢索格式化後的字串的總體度量。 文法 virtual HRESULT GetMetrics([out] DWRITE_TEXT_METRICS *textMetrics);參數 textMetrics [out] 此方法返回時,將包含格式化後文本與所關聯內容的度量距離。 傳回值 如果該方法成功,則返回 S_OK。 否則,將返回錯誤碼。HRESULT.
此函數的功能簡單的說,就是擷取IDWriteLayout物件版面配置後的文本資訊,使用參數來返回我們需要的資訊。
關於DWRITE_TEXT_METRICS類型的參數,這是一個結構體,用來盛放取出的文本布局資訊。我們來看一下它的成員:
// 布局後與文本相關的資訊 struct DWRITE_TEXT_METRICS { FLOAT left; // 格式化文本布局框的最左點 FLOAT top; // 格式化文本布局框的最上點 FLOAT width; // 格式化文本的寬度忽略多餘的空白處 FLOAT widthIncludingTrailingWhitespace; // 格式化文本的寬度,考慮每行結尾處的尾部空格 FLOAT height; // 格式化文本的高度,Null 字元串的高度由預設字型行高的大小決定 FLOAT layoutWidth; // 布局的初始寬度,根據文本是否被換行,它可以大於或小於常值內容寬度 FLOAT layoutHeight; // 布局的初始高度,根據文本的長度,它可以大於或小於常值內容高度 UINT32 maxBidiReorderingDepth; // 任一行文本的最大重新排序計數,用於計算點擊測試框的最大數量,如布局沒有雙向文本或根本沒有文本,則最小層級為1 UINT32 lineCount; // 文本的總行數 };
這個結構體的成員很多,而且都是一些非常有用的資訊啊。瞭解了DWRITE_TEXT_METRICS這個結構體之後,我們就知道取出的文本布局資訊都有什麼了。那我們除了擷取文字大小,還可以擷取文本的左上方座標、總行數等等資訊,看來我們可以從這瞭解很多文本的資訊了。
四、結語
上面的介紹應該讓大家可以完全理解了如何使用DirectWrite測量文本尺寸的過程了。
如有錯誤,歡迎指正。
使用DirectWrite測量Direct2D文字大小