转载请注明出处: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; // 格式化文本的高度,空字符串的高度由默认字体行高的大小决定 FLOAT layoutWidth; // 布局的初始宽度,根据文本是否被换行,它可以大于或小于文本内容宽度 FLOAT layoutHeight; // 布局的初始高度,根据文本的长度,它可以大于或小于文本内容高度 UINT32 maxBidiReorderingDepth; // 任一行文本的最大重新排序计数,用于计算命中测试框的最大数量,如布局没有双向文本或根本没有文本,则最小级别为1 UINT32 lineCount; // 文本的总行数
};

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

四、结语

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

如有错误,欢迎指正。

使用DirectWrite测量Direct2D文字大小的更多相关文章

  1. 自定义界面上绘制Text,可通过拖动控制文字大小及其位置

    项目地址 最近项目上有个需求,需要在一块区域中显示文字,这块区域可以拖动,也可以通过拖拽右下角来改变大小,里面的文字大小要根据区域的大小进行自适应.刚开始觉得这个需求不难,只需要一个TextView就 ...

  2. UIButton修改文字大小问题

    一.问题描述 通过UIButton对象font属性设置文字大小,却发现该属性在2.0.3.0就已经被废弃,ios不建议使用. 图1-1:点出UIButton对象的font属性提示被废弃 图1-2:UI ...

  3. html,CSS文字大小单位px、em、pt的关系换算

    html,CSS文字大小单位px.em.pt的关系换算 这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网页制作方面的一些缺陷.我一直也搞不清楚px与 ...

  4. 响应式十日谈第一日:使用 rem 设置文字大小

    上面回顾: 在序言中我们已经提到了响应式的一些基本理念,比如: 响应式网页不仅仅是响应不同类型的设备,而且需要响应不同的用户需求.响应式的初衷是为了让信息更好的传递交流,让所有人无障碍的获取信息,同时 ...

  5. TextView textSize 文字大小

    TextView,很常见的控件.关于文字大小的方法有: android.widget.TextView#getTextSize  返回值的单位是PX /** * @return the size (i ...

  6. ProgressDialog(四)——更改系统自带ProgressDialog文字大小

    MainActivity如下面: package com.example.ttt; import android.app.Activity; import android.app.ProgressDi ...

  7. iOS UIAlertView 文字对其方式 文字大小 设置方法

    - (void) willPresentAlertView:(UIAlertView *)alertView { for (UIView *subViewin alertView.subviews) ...

  8. Echarts 设置地图上文字大小及颜色

    Echarts 设置地图上文字大小及颜色,效果如下: 上代码:关键代码用红色 series: [ { //name: '香港18区人口密度', type: 'map', mapType: 'jiang ...

  9. CSS文字大小单位px、em、pt详解

    这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网页制作方面的一些缺陷.我一直也搞不清楚px与em之间的关系和特点,看过以后确实收获很大.平时都是用p ...

随机推荐

  1. 部分设备在微信内无法播放audio的解决方案

    临时接到一个紧急的需求,一个活动页面,在某台iPhone 5S设备上无法播放音频,其它设备均正常.我接到这个任务时,也是一脸懵逼,试过在audio标签上添加controls属性来显示audio,结果发 ...

  2. 【1】CommonCode快速代码集

    阅读目录 CommonCode是什么? CommonCode包括哪些内容? 版本信息   回到顶部 CommonCode是什么? 简单的说,CommonCode是作者在经历各种"试错&quo ...

  3. Python学习笔记(4):自定义时间类

    Python的时间我实在无法接受,太难用了.我觉得C#的时间就非常完美,简单.好用.所以,自定义了自己的时间类: 用法: 一个小小的应用,我需要取出每天股市交易的分钟段,开始是这样的: 稍微改进一下, ...

  4. Crontab中shell每分钟执行一次HDFS文件上传不执行的解决方案

    一.Crontab -e 加入输出Log */1 * * * * /qiwen_list/upload_to_hdfs.sh > /qiwen_list/mapred.log 2>& ...

  5. 转:电子取证中AVI文件的文件雕复

    电子取证中AVI文件的文件雕复 收藏本文 分享 1引言在电子取证工作中,恢复数字设备中被删除的数据是极为重要的工作之一,恢复数据又分依赖系统元信息的传统数据恢复技术和不依赖系统元信息的文件雕刻.文件雕 ...

  6. CentOS下httpd下php 连接mysql 本机可以,127.0.0.1不能访问

    你看到的这个文章来自于http://www.cnblogs.com/ayanmw php代码很简单: $server="127.0.0.1"; println("Begi ...

  7. liunx 服务内存消耗100% 怎么处理

      一.排查问题 查看内存使用 free 查看进程使用存储状况.看是不是业务进程在消耗存储,如果是就要优化业务代码了 使用top 命令 如果不是怎么办 二.处理办法 1.把没有用到的消耗内存的服务进程 ...

  8. Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  9. mediawiki的管理与使用

    本文主要讲述搭建好私有的mediawiki之后,管理员可能需要用到的几个功能.   维基百科的设计思路与我以往使用的系统不太一样,以管理员模式进入之后,并没有我预想的添加wiki页面入口,和侧边栏导航 ...

  10. 利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。

    利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示. import java.util.Scanner; public clas ...