Direct2D教程 绘制文本
概述
在Direct2D中,文本的绘制是通过DirectWrite来实现的,DirectWrite实际上已经是一个独立的DirectX组件了。关于DirectWrite,我摘录了MSDN的一段文字。
DirectWrite介绍
当今的应用程序应提供高质量的文本渲染,分辨率无关的字体及完整的Unicode文本和布局支持,DirectWrite提供了这些功能,甚至比这更多。下面是DirectWrite的特性
- 设备无关的文本布局系统,提高了文本的可读性(包括文档及UI上的文本)
- 高质量的,子像素,ClearType文本的渲染(可以使用GDI及Direct2D或应用程序指定的渲染技术)
- 硬件加速的文本渲染(和Direct2D一起使用时)
- 支持多格式文本
- 支持OpenType fonts的高级typography特性
- 对所支持语言文本的渲染及布局。
- GDI兼容的布局及渲染
DirectWrite API支持多格式文本的度量,绘制及命中测试。DirectWrite处理所有支持语言的文本,包括global及localized应用程序(构建于Windows7核心语言基础之上)。DirectWrite也提供了底层的glyph渲染。
Direct2D提供了如下两个绘制文本的函数,稍后的代码使用第一个函数。
- ID2D1RenderTarget::DrawText
- ID2D1RenderTarget::DrawTextLayout
主要步骤
这里介绍的步骤都是与绘制文本相关的核心步骤,其它步骤比如创建render target或者画刷,处理Windows消息等是每个Direct2D程序都会涉及的,这里就不再介绍了。
创建ID2D1Factory接口对象
凡事都有个根源,程序也是一样,在Direct2D中也有一个根源对象,那就是ID2D1Factory接口,它是所有其它资源的根源,包括设备相关的资源及设备无关的资源,有了这个接口,就可以创建其它的D2D对象了,比如render target,画刷等。所以首要任务是创建一个ID2D1Factory对象。
D2D1Factory* g_pD2DFactory = NULL;
HRESULT hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory
);
if(FAILED(hr))
{
MessageBox(NULL, L"Create Direct2D factory failed!", L"Error", 0); return;
}
创建IDWriteFactory接口对象
前面说了,在Direct2D中绘制文本实际上是通过DirectWrite来实现的,一切和文本相关的接口也都是由这个接口来创建的,所以接下来要创建一个IDWriteFactory接口对象,代码如下。
IDWriteFactory* g_pDWriteFactory = NULL;// Create DirectWrite Factoryhr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&g_pDWriteFactory)
);
if(FAILED(hr))
{
MessageBox(NULL, L"Create DirectWrite factory failed!", L"Error", 0); return;
}
创建IDWriteTextFormat接口对象
文本有一系列属性,比如字体类型,Arial还是Consolas?字体大小,14px还是16px? 字体风格,倾斜或加粗?在D2D中,用IDWriteTextFormat来描述文本的这些属性,所以,下一步需要创建IDWriteTextFormat对象了。需要注意的是文本的颜色并不是由该接口来控制的,而是由画刷来控制。
IDWriteTextFormat* g_pTextFormat = NULL;
hr = g_pDWriteFactory->CreateTextFormat(
L"Gabriola", // Font family name
NULL, // Font collection(NULL sets it to the system font collection)
DWRITE_FONT_WEIGHT_REGULAR, // Weight
DWRITE_FONT_STYLE_NORMAL, // Style
DWRITE_FONT_STRETCH_NORMAL, // Stretch
50.0f, // Size
L"en-us", // Local
&g_pTextFormat // Pointer to recieve the created object );
if(FAILED(hr))
{
MessageBox(NULL, L"Create IDWriteTextFormat failed!", L"Error", 0); return;
}
定义文本绘制区域
下一步,需要确定文本的绘制区域,也就是在哪里绘制文本,这个区域通常是一个矩形结构。所以,只需简单定义一个rect即可。
// Create text layout rectRECT rc;
GetClientRect(hwnd, &rc);
D2D1_RECT_F textLayoutRect = D2D1::RectF(
static_cast<FLOAT>(rc.left),
static_cast<FLOAT>(rc.top),
static_cast<FLOAT>(rc.right - rc.left),
static_cast<FLOAT>(rc.bottom - rc.top)
);
绘制
万事俱备,只欠东风!下面就是最后一步也是最重要的一步,渲染文本,这里使用接口ID2D1HwndRenderTarget中的函数DrawText来完成具体的绘制工作,这个函数的具体定义如下:
virtual void DrawText(
[in] WCHAR *string,
UINT stringLength,
[in] IDWriteTextFormat *textFormat,
[in] const D2D1_RECT_F *layoutRect,
[in] ID2D1Brush *defaultForegroundBrush,
D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE,
DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL
) = 0;
参数说明:
- string, 待绘制的文本,unicode编码。
- stringLength, 文本长度。
- textFormat, 文本的格式化信息(属性),上面提到过。
- layoutRect, 绘制区域对应的矩形。
- defaultForegroundBrush, 绘制文本所用的画刷
最后两个参数暂时用不到,而且有默认参数,这里就不考虑了。调用代码如下。
// Draw textg_pRenderTarget->DrawText(
wszText, // Text to render
cTextLength, // Text length
g_pTextFormat, // Text format
textLayoutRect, // The region of the window where the text will be rendered
g_pBlackBrush // The brush used to draw the text);
效果图