使用DirectWrite测量Direct2D文字大小

发表于2017-07-26
评论0 2k浏览

在开发的时候有些文本标签的尺寸不好控制,经常会出现问题,为此,下面这篇文章和大家介绍一下如何使用DirectWrite来测量Direct2D文本的大小,希望能对大家有用。


一、概述

最近在使用Direct2D和DirectWrite写引擎,在引擎中需要实现文本标签控件。但是文本标签的尺寸最好不是由我们人为指定的,要不然的话就会出现标签中文本溢出、空白存留等等问题,这样很影响美观。这就需要我们在文本标签的创建时根据文本的字体格式、文字排版等等因素来确定标签大小,而不是人为地指定大小,即实现标签大小的自适应功能(根据文本的内容、字体、格式等等因素得出的宽高来设置标签的大小)。

然而,想要实现标签大小的自适应功能,就需要测量Direct2D文本的大小。但是,如何测量Direct2D文字的大小呢,我在Direct2D中找了很久也没有找到合适的方法,在搜索引擎中也没有找到理想的解决方法。最后,在DirectWrite的MSDN文档中找到了解决方法。

那下面就来看看怎么使用DirectWrite来测量Direct2D文本的大小。

 

二、解决方法

以下是我实现的一段用于测量文本宽高尺寸的函数,先贴代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用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(),我们需要的文本大小信息就可以通过这个函数来获取。重点介绍一下这个函数:

1
2
3
4
5
6
7
8
9
IDWriteTextLayout::GetMetrics 方法介绍
功能
    检索格式化后的字符串的总体度量。
语法
    virtual HRESULT GetMetrics([out]  DWRITE_TEXT_METRICS *textMetrics);
参数 textMetrics [out]    
    此方法返回时,将包含格式化后文本与所关联内容的度量距离。
返回值    
    如果该方法成功,则返回 S_OK。 否则,将返回错误代码。HRESULT.

此函数的功能简单的说,就是获取IDWriteLayout对象布局后的文本信息,使用参数来返回我们需要的信息。


关于DWRITE_TEXT_METRICS类型的参数,这是一个结构体,用来盛放取出的文本布局信息。我们来看一下它的成员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 布局后与文本相关的信息
struct DWRITE_TEXT_METRICS
{    
    FLOAT left; // 格式化文本布局框的最左点    
 
    FLOAT top; // 格式化文本布局框的最上点
 
    FLOAT width; // 格式化文本的宽度忽略多余的空白处  
 
    FLOAT widthIncludingTrailingWhitespace; // 格式化文本的宽度,考虑每行结尾处的尾部空格  
 
    FLOAT height; // 格式化文本的高度,空字符串的高度由默认字体行高的大小决定    
 
    FLOAT layoutWidth; // 布局的初始宽度,根据文本是否被换行,它可以大于或小于文本内容宽度    
 
    FLOAT layoutHeight; // 布局的初始高度,根据文本的长度,它可以大于或小于文本内容高度
     
    UINT32 maxBidiReorderingDepth; // 任一行文本的最大重新排序计数,用于计算命中测试框的最大数量,如布局没有双向文本或根本没有文本,则最小级别为1    
 
    UINT32 lineCount; // 文本的总行数    
};        

这个结构体的成员很多,而且都是一些非常有用的信息啊。了解了DWRITE_TEXT_METRICS这个结构体之后,我们就知道取出的文本布局信息都有什么了。那我们除了获取文本大小,还可以获取文本的左上角坐标、总行数等等信息,看来我们可以从这了解很多文本的信息了。

 

四、结语

上面的介绍应该让大家可以完全理解了如何使用DirectWrite测量文本尺寸的过程了。

如有错误,欢迎指正。

作者:郭小雷
出处:http://www.cnblogs.com/Ray1024/

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: