图形系统中为了获得当前运行程序的相关信息,往往需要在屏幕上显示文本,Direct3D的功能扩展接口ID3DXFont对此提供了方便的解决方法。
创建ID3DXFont对象
使用接口ID3DXFont绘制文本,首先需要通过函数D3DXCreateFont()创建ID3DXFont字体对象。ID3DXFont接口封装了Windows字体和Direct3D设备指针,D3DXCreateFont()函数通过Windows字体和Direct3D设备指针创建ID3DXFont对象,该函数的声明如下:
Creates a font object for a device and font.
HRESULT D3DXCreateFont(
LPDIRECT3DDEVICE9 pDevice,
INT Height,
UINT Width,
UINT Weight,
UINT MipLevels,
BOOL Italic,
DWORD CharSet,
DWORD OutputPrecision,
DWORD Quality,
DWORD PitchAndFamily,
LPCTSTR pFacename,
LPD3DXFONT * ppFont
);
Parameters
- pDevice
- [in] Pointer to an IDirect3DDevice9 interface, the
device to be associated with the font object.
- Height
- [in] The height of the characters in logical
units.
- Width
- [in] The width of the characters in logical units.
- Weight
- [in] Typeface weight. One example is bold.
- MipLevels
- [in] The number of mipmap levels.
- Italic
- [in] True for italic font, false otherwise.
- CharSet
- [in] The character set of the font.
- OutputPrecision
- [in] Specifies how Windows should attempt to match
the desired font sizes and characteristics with actual fonts. Use
OUT_TT_ONLY_PRECIS for instance, to ensure that you always get a TrueType
font.
- Quality
- [in] Specifies how Windows should match the
desired font with a real font. It applies to raster fonts only and should
not affect TrueType fonts.
- PitchAndFamily
- [in] Pitch and family index.
- pFacename
- [in] String containing the typeface name. If the
compiler settings require Unicode, the data type LPCTSTR resolves to
LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See Remarks.
- ppFont
- [out] Returns a pointer to an ID3DXFont interface,
representing the created font object.
Return Values
If the function succeeds, the return value is S_OK. If
the function fails, the return value can be one of the following:
D3DERR_INVALIDCALL, D3DXERR_INVALIDDATA, E_OUTOFMEMORY.
Remarks
The creation of an ID3DXFont object requires that the
device supports 32-bit color.
The compiler setting also determines the function
version. If Unicode is defined, the function call resolves to D3DXCreateFontW.
Otherwise, the function call resolves to D3DXCreateFontA because ANSI strings
are being used.
If you want more information about font parameters, see
The Logical Font.
示例代码如下:
D3DXCreateFont(g_device, 50, 20, 20,
0, FALSE, DEFAULT_CHARSET, 0, 0, 0, "Arial", &g_font);
使用ID3DXFont对象绘制二维文本
创建了ID3DXFont对象后,就可以使用其接口函数ID3DXFont::DrawText()在指定位置绘制二维文本,该函数支持ANSI和双字节字符串,声明如下:
Draws formatted text. This method supports ANSI and
Unicode strings.
INT DrawText(
LPD3DXSPRITE pSprite,
LPCTSTR pString,
INT Count,
LPRECT pRect,
DWORD Format,
D3DCOLOR Color
);
Parameters
- pSprite
- [in] Pointer to an ID3DXSprite object that
contains the string. Can be NULL, in which case Direct3D will render the
string with its own sprite object. To improve efficiency, a sprite object
should be specified if ID3DXFont::DrawText is to be called more than once in
a row.
- pString
- [in] Pointer to a string to draw.If the Count
parameter is -1, the string must be null-terminated.
- Count
- [in] Specifies the number of characters in the
string. If Count is -1, then the pString parameter is assumed to be a
pointer to a null-terminated string and ID3DXFont::DrawText computes
the character count automatically.
- pRect
- [in] Pointer to a RECT structure that contains the
rectangle, in logical coordinates, in which the text is to be formatted. As
with any RECT object, the coordinate value of the rectangle's right side
must be greater than that of its left side. Likewise, the coordinate value
of the bottom must be greater than that of the top.
- Format
- [in] Specifies the method of formatting the text.
It can be any combination of the following values:
- DT_BOTTOM
- Justifies the text to the bottom of the
rectangle. This value must be combined with DT_SINGLELINE.
- DT_CALCRECT
- Determines the width and height of the
rectangle. If there are multiple lines of text, ID3DXFont::DrawText
uses the width of the rectangle pointed to by the pRect parameter and
extends the base of the rectangle to bound the last line of text. If
there is only one line of text, ID3DXFont::DrawText modifies the
right side of the rectangle so that it bounds the last character in the
line. In either case, ID3DXFont::DrawText returns the height of
the formatted text but does not draw the text.
- DT_CENTER
- Centers text horizontally in the rectangle.
- DT_EXPANDTABS
- Expands tab characters. The default number of
characters per tab is eight.
- DT_LEFT
- Aligns text to the left.
- DT_NOCLIP
- Draws without clipping. ID3DXFont::DrawText
is somewhat faster when DT_NOCLIP is used.
- DT_RIGHT
- Aligns text to the right.
- DT_RTLREADING
- Displays text in right-to-left reading order
for bidirectional text when a Hebrew or Arabic font is selected. The
default reading order for all text is left-to-right.
- DT_SINGLELINE
- Displays text on a single line only. Carriage
returns and line feeds do not break the line.
- DT_TOP
- Top-justifies text.
- DT_VCENTER
- Centers text vertically (single line only).
- DT_WORDBREAK
- Breaks words. Lines are automatically broken
between words if a word would extend past the edge of the rectangle
specified by the pRect parameter. A carriage return/line feed sequence
also breaks the line.
- Color
- [in] Color of the text. For more information, see
D3DCOLOR.
Return Values
If the function succeeds, the return value is the
height of the text in logical units. If DT_VCENTER or DT_BOTTOM is specified,
the return value is the offset from pRect (top to the bottom) of the drawn text.
If the function fails, the return value is zero.
Remarks
The parameters of this method are very similar to those
of the GDI DrawText function.
This method supports both ANSI and Unicode strings.
This method must be called inside a
IDirect3DDevice9::BeginScene ... IDirect3DDevice9::EndScene block. The only
exception is when an application calls ID3DXFont::DrawText with
DT_CALCRECT to calculate the size of a given block of text.
Unless the DT_NOCLIP format is used, this method clips
the text so that it does not appear outside the specified rectangle. All
formatting is assumed to have multiple lines unless the DT_SINGLELINE format is
specified.
If the selected font is too large for the rectangle,
this method does not attempt to substitute a smaller font.
This method supports only fonts whose escapement and
orientation are both zero.
示例代码如下:
g_device->BeginScene();
DWORD format = DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER;
g_font->DrawText(NULL, g_text, (INT) strlen(g_text), &g_client_rect, format,
0xFFFFFF00);
g_device->EndScene();
ID3DXFont其他相关接口函数
函数ID3DXFont::GetDevice()能够获得与ID3DXFont相关联的Direct3D设备指针,该函数声明如下:
Retrieves the Direct3D device associated with the font
object.
HRESULT GetDevice(
LPDIRECT3DDEVICE9 * ppDevice
);
Parameters
- ppDevice
- [out] Address of a pointer to an IDirect3DDevice9
interface, representing the Direct3D device object associated with the font
object.
Return Values
If the method succeeds, the return value is S_OK. If
the method fails, the return value can be one of the following:
D3DERR_INVALIDCALL, D3DXERR_INVALIDDATA.
Remarks
Note Calling this method
will increase the internal reference count on the IDirect3DDevice9
interface. Be sure to call IUnknown when you are done using this
IDirect3DDevice9 interface or you will have a memory leak.
示例截图:
源程序:
#include <D3D9.h>
#include <D3DX9Core.h>
#pragma warning(disable : 4127)
#define CLASS_NAME "GameApp"
#define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0)
IDirect3D9* g_d3d;
IDirect3DDevice9* g_device;
ID3DXFont* g_font;
RECT g_client_rect;
const char* g_text = "Welcome to Direct3D!";
bool init_d3d(HWND hwnd)
{
g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(g_d3d == NULL)
return false;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_device)))
{
return false;
}
/*
D3DXCreateFontA(
LPDIRECT3DDEVICE9 pDevice,
INT Height,
UINT Width,
UINT Weight,
UINT MipLevels,
BOOL Italic,
DWORD CharSet,
DWORD OutputPrecision,
DWORD Quality,
DWORD PitchAndFamily,
LPCSTR pFaceName,
LPD3DXFONT* ppFont);
*/
D3DXCreateFont(g_device, 50, 20, 20, 0, FALSE, DEFAULT_CHARSET, 0, 0, 0, "Arial", &g_font);
GetClientRect(hwnd, &g_client_rect);
return true;
}
void cleanup()
{
release_com(g_font);
release_com(g_device);
release_com(g_d3d);
}
void render()
{
g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);
g_device->BeginScene();
DWORD format = DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER;
g_font->DrawText(NULL, g_text, (INT) strlen(g_text), &g_client_rect, format, 0xFFFFFF00);
g_device->EndScene();
g_device->Present(NULL, NULL, NULL, NULL);
}
LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_CLASSDC;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = inst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASS_NAME;
wc.hIconSm = NULL;
if(! RegisterClassEx(&wc))
return -1;
HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
NULL, NULL, wc.hInstance, NULL);
if(hwnd == NULL)
return -1;
if(init_d3d(hwnd))
{
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
render();
Sleep(10);
}
}
cleanup();
UnregisterClass(CLASS_NAME, wc.hInstance);
return 0;
}