之前一边做脚本引擎,一边山寨一个自绘的native C++的GUI框架并且可以切换GDI或者Direct2D渲染模式。因为抄了WPF的那种高级自动布局功能,所以必然需要知道如何测量文字大小。Direct2D测量文字大小比较麻烦,不像GDI有直接函数,并且用中英文搜好像都没人直接给出结果,还有人在博客上写“这种事情好像办不到”这样的文字。不过经过我遍历MSDN,还是找到了一个曲线救国的方法的,直接上代码:
首先是创建IDWriteTextFormat:
1
IDWriteFactory
*
dwriteFactory
=
GetDirectWriteFactory();
2
IDWriteTextFormat
*
format
=
0
;
3
HRESULT hr
=
dwriteFactory
->
CreateTextFormat(
4
fontProperties.fontFamily.Buffer(),
5
NULL,
6
(fontProperties.bold
DWRITE_FONT_WEIGHT_BOLD:DWRITE_FONT_WEIGHT_NORMAL),
7
(fontProperties.italic
DWRITE_FONT_STYLE_ITALIC:DWRITE_FONT_STYLE_NORMAL),
8
DWRITE_FONT_STRETCH_NORMAL,
9
(FLOAT)fontProperties.size,
10
L
""
,
11
&
format);
12
if
(
!
FAILED(hr))
13
{
14
format
->
SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
15
return
format;
16
}
17
else
18
{
19
return
0
;
20
}
fontProperties是我自定义的一个结构就不用去管它了,参考MSDN就知道CreateTextFormat如何使用了。其中fontProperties.fontFamily是字体的名字。然后IDWriteTextFormat就扮演着GDI的“字体对象”的角色,可以用ID2D1RenderTarget进行绘制。ID2D1RenderTarget除了用IDWriteTextFormat当字体以外,还可以用IDWriteTextLayout当“添加多余信息的更复杂的字体”。测量文字的关键正是在这里。
接下来我们借助IDWriteTextFormat来创建IDWriteTextLayout:
1
IDWriteTextLayout
*
textLayout
=
0
;
2
HRESULT hr
=
GetDirectWriteFactory()
->
CreateTextLayout(
3
oldText.Buffer(),
4
oldText.Length(),
5
textFormat,
6
0
,
7
0
,
8
&
textLayout);
9
if
(
!
FAILED(hr))
10
{
11
DWRITE_TEXT_METRICS metrics;
12
hr
=
textLayout
->
GetMetrics(
&
metrics);
13
if
(
!
FAILED(hr))
14
{
15
minSize
=
Size((
int
)ceil(metrics.widthIncludingTrailingWhitespace), (
int
)ceil(metrics.height));
16
}
17
textLayout
->
Release();
18
return
;
19
}
这里看minSize就知道如何测量文字的字体了。
在这里放一张暂时的图片。我抄了WPF的那种方法,从布局和绘图元素直接开始可以构造GUI,因此演示了如何使用这些东西来创造一个Win7的按钮(带动画的哦)打开Vczh Library++3.0,下载代码并打开Candidate\GUI\GuiDemo\GuiDemo.sln,按F5就可以看到了效果了:

这一个是Direct2D渲染的结果(我在工程文件指定了DXSDK的绝对路径,如果你们安装的地方不同改掉它