学习目标:
D3DX 库提供接口 ID3DXFont ,该接口用于在 Direct3D 应用程序中绘制文本。该接口内部使用 GDI(图像设备接口)来绘制文本,因此该接口在性能上略有损失。然而正是由于该接口使用了 GDI,所以才能够处理一些复杂的字体和格式。
创建一个 ID3DXFont 接口对象
我们可以用 D3DXCreateFontIndirect 函数来创建一个 ID3DXFont 接口对象。
HRESULT D3DXCreateFontIndirect(
LPDIRECT3DDEVICE9 pDevice, //要与字体关联的设备
const D3DXFONT_DESC* pDesc, //D3DXFONT_DESC字符串结构
LPD3DXFONT* ppFont //返回创建的字体
);
下面的代码段演示了如何使用该函数
D3DXFONT_DESC df;
ZeroMemory(& df, sizeof(D3DXFONT_DESC));
df.Height = 25; //高度,逻辑单位
df.Width = 12; //宽度,逻辑单位
df.Weight = 500; //粗体范围
df.MipLevels = D3DX_DEFAULT;
df.Italic = false;
df.CharSet = DEFAULT_CHARSET;
df.OutputPrecision = 0;
df.Quality = 0;
df.PitchAndFamily = 0;
strcpy(df.FaceName, "Times New Roman");//字体样式
ID3DXFont* font = 0;
D3DXCreateFontIndirect(Device, & df, & font);
为了对我们想要创建的字体进行描述,必须先填充 D3DXFONT_DESC 结构。
绘制文本:
一旦获取了 ID3DXFont 接口的指针,只需调用方法 ID3DXFont::DrawText 即可轻而易举的完成文本的绘制。
INT ID3DXFont::DrawText(
LPD3DXSPRITE pSprite, //指定字符串所属的ID3DXSprite对象接口,可设为0或NULL,表示在当前中绘制字符串
LPCSTR pString, //指向将要绘制的字符串的指针
INT Count, //字符串中的字符个数,若该值为-1,则认为参数pString指向一个以NULL结尾的字符串。ID3DXFont::DrawText 方法将自动对字符个数进行统计。
LPRECT pRect, //指定字符串绘制的矩形区域的位置
DWORD Format, //指定了字符串在pRect指定的矩形区域中的格式化方法,该方法是一系列可选标记的某一个或某种组合,详情参阅SDK文档
D3DCOLOR Color //文本颜色
);
例:
Font->DrawText(
NULL,
"Hello, World",
-1,
& rect,
DT_TOP | DT_LEFT,
0xff000000
);
该类无法使用
由于 CD3DFont 类绘制文本时使用的是 Direct3D 而非 GDI,所以其绘制的速度比 ID3DXFont 要快的多,但该类也有缺陷,CD3DFont 类不支持 ID3DXFont 所支持的那些复杂的字体和格式。如果您很在意速度,而且简单字体即能满足需求,CD3DFont 类便是一个很好的选择。
创建 CD3DFont 类的实例
要创建 CD3DFont 类的实例,我们只需要像普通C++对象那样进行实例化即可,下面是该类的构造函数原型:
CD3DFont(const TCHAR * strFontName, DWORD dwHeight, DWORD dwFlags = 0L)
当我们实例化一个CD3DFont 类的对象后,必须调用如下方法来对字体进行初始化:
Font = new CD3DFont("Times New Roman",16,0);
Font->InitDeviceObject(Device);
Font->RestoreDeviceObjects();
绘制文本
既然我们已经创建来一个 CD3DFont 对象并对其进行了初始化,现在我们就可绘制一些文本,可用如下函数实现文本的绘制:
HRESULT CD3DFont::DrawText(
FLOAT x, //屏幕坐标系中绘制起点的x坐标
FLOAT y, //屏幕坐标系中绘制起点的y坐标
DWORD dwColor, //文本的颜色
const TCHAR* strText, //指向所要绘制文本的指针
DWORD dwFlags = 0); //绘制标记,可选,该参数为0或下列标记的组合
D3DFONT_CENTERED D3DFONT_TWOSIDED D3DFONT_FILTERED
清理
在删除一个 CD3DFont 类的对象之前,我们必须首先调用一些清理函数,如下面的代码段所示:
Font->InvalidateDeviceObjects();
Font->DeleteDeviceObjects();
delete Font;
该函数用于创建文本的 3D网格
D3DXCreateText 函数的原型为:
HRESULT D3DXCreateText(
LPDIRECT3DDEVICE9 pDevice, //指向与网格相关的设备
HDC hDC, //一个设备环境句柄,它包含了将用来创建网格的字体的相关信息
LPCTSTR pText, //指向确定所要用于生成文本的字符串指针
FLOAT Deviation, //True Type 字体轮廓的最大弦偏差,该值必须为负,弦偏差等于原始字体的一个设计单位
FLOAT Extrusion, //沿Z轴负方向度量的字体深度
LPD3DXMESH* ppMesh, //返回所创建的网格
LPD3DXBUFFER* ppAdjacency, //返回所创建的网格的邻接信息,如果不需要,指定为NULL
LPGLYPHMETRICSFLOAT pGlyphMetrics //指向LPGLYPHMETRICSFLOAT 类型结构数组的指针,该结构包含了字形的度量数据,如果不关心字形的度量数据,可将该值设为0
);
//如果调用成功,该函数返回 D3D_OK
例程代码
//获取设备上下文的句柄
HDC hdc = CreateCompatibleDC(0);
HFONT hFont;
HFONT hFontOld;
//填写描述字体属性的logFont结构
LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));
lf.lfHeight =25; //以逻辑单位表示
lf.lfWidth =12; //以逻辑单位表示
lf.lfEscapement =0;
lf.lfOrientation =0;
lf.lfWeight =500; //粗体,范围0(浅色)-1000(粗体)
lf.lfItalic =false;
lf.lfUnderline =false;
lf.lfStrikeOut =false;
lf.lfCharSet =DEFAULT_CHARSET;
lf.lfOutPrecision =0;
lf.lfClipPrecision =0;
lf.lfQuality =0;
lf.lfPitchAndFamily =0;
strcpy(lf.lfFaceName, "Times New Roman"); //字体样式
//创建字体并使用设备上下文选择该字体
hFont = CreateFontIndirect(&lf);
hFontOld = (HFONT)SelectObject(hdc, hFont);
//基于hdc中选定的字体创建文本网格
D3DXCreateText(Device, hdc, "Direct3D", 0.001f, 0.4f, &Text, 0, 0);
//重置旧字体并释放资源
SelectObject(hdc, hFontOld);
DeleteObject(Hfont);
DeleteDC(hdc);
//绘制3D文本网格仅需要调用网格的 DrawSubset 方法即可
Text->DrawSubset(0);