Windows 系统中经常使用 GDI 进行文本输出,从某种意义上来说,图形和文本并没有本质上的界限,很多时候 windows 把文本也当作图形对待。在 windows 编程中,文本操作首先要获得文本句柄,此外,还要设置字体,字符大小,字符颜色等有关属性,并将它们选入设备环境。
设置文本的设备环境
1. 自定义字体
可以使用函数 CreateFont 自定义字体
HFONT hFont = HFONT CreateFont(
int nHeight, int nWidth, // 字体高,宽
int nEscapement, // 文字相对于页底的角度
int nOrientation, // 每个文字相对于页底的角度
int fnWeight, // 字体粗细,范围 0~1000 , 400 为正常字体, 700 为黑体
DWORD fdwItalic, // 取非零值则为斜体
DWORD fdwUnderline, // 取非零值则下划线
DWORD fdwStrikeOut, // 取非零值则中划线
DWORD fdwCharSet, // 字体所属字符集
DWORD fdwOutputPrecision, // 输出精度(一般取默认值)
DWORD fdwClipPrecision, // 剪裁精度(一般取默认值)
DWORD fdwQuality, // 输出质量(一般取默认值)
DWORD fdwPitchAndFamily, // 字体间距及字体系列(一般取默认值)
LPCTSTR lpszFace // 字体名
);
这个这个......以后这样建字体还不累死才怪咧!而且貌似 API 里带这么多恶心参数的方法还不少,了解一下就行了。一般情况下使用系统默认提供的字体就可以了。
2. 字体句柄
windows 系统提供了七种基本字体:
ANSI_FIXED_FONT , DEFAULT_GUI_FONT , ANSI_VAR_FONT
DEVICE_DEFAULT_FONT , SYSTEM_FIXED_FONT ,
SYSTEM_FONT (系统默认字体)
调用函数 GetStockObject ()即可获得系统默认字体
获得字体之后,有时候还需要设置字体颜色和背景色,可以使用下面两个函数:
SetTextColor // 设置字体颜色
SetBkColor // 设置背景颜色
文本输出过程
设置了字体句柄,字体及字体颜色之后就可以把设置字体输入到相应的设备上。 Windows 系统在文本输出上有点小小的偷懒,把很多事情都丢给了程序员来做,应用程序必须自己管理换行,后续字符的位置等输出格式。虽提供了编程的自由,但是程序员的工作量也变的非常大。
文本输出过程包括获取字体信息,格式化文本,调用函数输出文本等过程。
1. 获取字体信息
应用程序在输出字体之前必须先获取当前字体的有关信息,在 windows 程序中通过调用 GetTextMetrics 函数来获取当前字体的信息。其形式为:
GetTextMetrics(hdc, &tm); //tm 为 TEXTMETRIC 结构
TEXTMETRIC 结构也非常复杂,其结构定义如下:
typedef struct tagTEXTMETRIC {
LONG tmHeight;
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
LONG tmAveCharWidth;
LONG tmMaxCharWidth;
LONG tmWeight;
LONG tmOverhang;
LONG tmDigitizedAspectX;
LONG tmDigitizedAspectY;
TCHAR tmFirstChar;
TCHAR tmLastChar;
TCHAR tmDefaultChar;
TCHAR tmBreakChar;
BYTE tmItalic;
BYTE tmUnderlined;
BYTE tmStruckOut;
BYTE tmPitchAndFamily;
BYTE tmCharSet;
} TEXTMETRIC, *PTEXTMETRIC;
具体各属性不解释,需要时可以查询 MSDN 。
2. 格式化文本
格式化处理一般针对两种情况,一是文本行中确定后续文本的坐标,二是在换行时确定下一行的坐标。
(1) 确定后续文本坐标
应先获取当前字符的宽度,通过计算字符串起始坐标与字符串宽度之和即可得到后续文本的起始坐标。
这里要使用到函数:
BOOL GetTextExtentPoint32
(
HDC hdc,
LPCTSTR lpsxString, // 指定的字符串
int nLength, // 字符串中字符数
LPSIZE lpSize // 字符串宽度及高度的 SIZE 数据结构
)
(2) 确定换行时文本坐标
通过计算当前文本行字符的高度与行间隔之和,即可得到换行时文本的起始坐标,而上述两个数值均可通过获取当前字体信息得到。
3. 文本输出
最常用的文本输出函数就是 TextOut ,其原型如下:
BOOL TextOut
(
HDC hdc,
int x, int y,
LPCTSTR lpString,
int nCount
) 文本操作实例
因为代码太长,全部贴出来页面不好看。故只给出WndProc函数的实现,程序其它部分可以参考以前的笔记。
UINT wParam,
LONG lParam)
{
HDC hdc;
HFONT hFont; // 字体句柄
PAINTSTRUCT ps;
TEXTMETRIC tm;
char lpszTx1[] = " 红色的SYSTEM字体:好好学习,天天向上! " ;
char lpszTx2[] = " 绿色自定义字体:保护眼睛,注意休息! " ;
char lpszTx3[] = " 蓝色大号斜体并带有下划线! " ;
char lpszTx4[] = " 两行文本输出到同一行里! " ;
char lpszTx5[] = " 今天的学习就到这里,祝你成功! " ;
int x = 0 , y = 0 ;
SIZE size;
switch (iMsg)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, & ps);
SetTextColor(hdc, RGB( 255 , 0 , 0 )); // 文本为红色
TextOut(hdc, x, y, lpszTx1, strlen(lpszTx1)); // 字体输出
GetTextMetrics(hdc, & tm); // 获取系统当前字体
y = y + tm.tmHeight + tm.tmExternalLeading; // 计算下一行坐标
hFont = CreateFont
(
20 , 0 , // 高度20, 宽取0表示由系统选择最佳值
0 , 0 , // 文本倾斜,与字体倾斜都为0
FW_HEAVY, // 粗体
0 , 0 , 0 , // 非斜体,无下划线,无中划线
GB2312_CHARSET, // 字符集
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, // 一系列的默认值
DEFAULT_PITCH | FF_DONTCARE,
" 自定义字体 " // 字体名称
);
SetTextColor(hdc, RGB( 0 , 255 , 0 ));
SelectObject(hdc, hFont);
TextOut(hdc, x, y, lpszTx2, strlen(lpszTx2));
GetTextMetrics(hdc, & tm); // 将当前字体信息选入tm结构中
y = y + tm.tmHeight + 15 * tm.tmExternalLeading; // 5倍行间距
hFont = CreateFont
(
40 , 0 , // 高度40, 宽取0表示由系统选择最佳值
0 , 0 , // 文本倾斜,与字体倾斜都为0
FW_NORMAL,
1 , 1 , 0 , // 斜体,下划线,无中划线
GB2312_CHARSET, // 字符集
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, // 一系列的默认值
DEFAULT_PITCH | FF_DONTCARE,
" 大号字体 " // 字体名称
);
SetTextColor(hdc, RGB( 0 , 0 , 255 ));
SetBkColor(hdc, RGB( 160 , 160 , 160 )); // 设置背景颜色
SelectObject(hdc, hFont);
TextOut(hdc, x, y, lpszTx3, strlen(lpszTx3));
// 获取系统提供的字体
hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT);
y = y + tm.tmHeight + 25 * tm.tmExternalLeading;
SetTextColor(hdc, RGB( 0 , 0 , 0 ));
SetBkColor(hdc, RGB( 255 , 255 , 255 ));
SelectObject(hdc, hFont);
TextOut(hdc, x, y, lpszTx4, strlen(lpszTx4));
GetTextExtentPoint32(hdc, lpszTx4, strlen(lpszTx4), & size); // 计算高宽
x = x + size.cx;
TextOut(hdc, x , y ,lpszTx5, strlen(lpszTx5));
EndPaint(hWnd, & ps);
DeleteObject(hFont);
break ;
case WM_DESTROY:
PostQuitMessage( 0 );
break ;
default :
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
return 0 ;
}