文本输出是应用程序经常需要实现的功能。许多程序的运行结果都必须以文本输出形式显示;文字处理程序更是主要以文本作为处理的对象。所以,程序员掌握文本输出的基本原理和技术具有重要的意义。文本输出需要解决的问题是如何修改显示文本的字体、颜色和大小,以及如何协调在不同设备上显示文本的差异。
第一节 文本输出的基本知识
1.文本的设备描述表属性
设备描述表( Device Context)是一个决定输出的位置和外形的属性集合。在用户编制的应用程序中可以通过设备描述表句柄间接地读取设备描述表。当程序为设备描述表申请一个句柄时,系统就自动生成了一个设备描述表,生成的设备描述表包含了所有属性的默认值。其中与文本有关的默认值如表所示。
属性意义
|
默认值
|
背景色 | White |
字体 | SYSTEM_FONT |
字符间隔 | 0 |
文本颜色 | Black |
背景模式 | OPAQUE |
背景色定义了填充字符,以及填充字符间区域的颜色。背景模式有两种取值:OPAQUE 和 TRANSPARENT。默认值为 OPAQUE表示背景颜色有效;如果设定为TRANSPARENT,则表示关闭背景色。字符间距和文本颜色分别表示两个字符间的间隔和字体的颜色。
2.字体
字体描述了所显示字符的大小、外形和种类,也就是说字体包含了字符集中每个字符属性的抽象描述。字体分为两种基本类型:物理字体和逻辑字体。GDI(图形设备接口)常用的字体如表所示。
常用GDI字体族举例
字体
|
字体常量
|
Dontcare | FF_DONTCARE |
Decorative | FF_DECORATIVE |
Modem | FF_MODEM |
Roman | FF_ROMAN |
Script | FF_SCRIPT |
Switss | FF_SWITSS |
3.文本度量和文本对齐
文本度量是指文本的所有尺寸信息。可以通过GetTextMetrics函数获得这些信息,并将这些信息保存在一个TEXTMETRIC结构体变量中。文本对齐是指按照指定的坐标和基准线来排列文本。可以调用SetTextAlign函数来设置当前文本的对齐属性。SetTextAlign
函数的原型定义如下:
UINT SetTextAlign(
HDC hdc, // 设备描述表句柄
UINT fMode // 对齐属性常量
)
其中对齐属性常量的取值如表所示。
取值
|
意义
|
TA_BASELINE | 参考点在基线上 |
TA_BOTTOM | 参考点在矩形界的底部 |
TA_TOP | 参考点在矩形界的顶部 |
TA_CENTER | 参考点在边界矩形的中部 |
TA_LEFT | 参考点在矩形边界的最左边 |
TA_RIGHT | 参考点在矩形边界的最右边 |
字体输出实例
字体输出演示程序
#include<Windows.h>
//全局变量
HINSTANCE hInst; // 当前句柄
TCHAR szTitle[]=“字体输出实例”; // 标题栏文本
TCHAR szWindowClass[50]="fonttest"; // 窗口类名
//函数原型
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//作用:入口函数
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//函数:MyRegisterClass
//作用:注册窗口类
ATOM MyRegisterClass (HINSTANCE hInstance)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style= CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc= (WNDPROC)WndProc;
wndclass.cbClsExtra= 0;
wndclass.cbWndExtra= 0;
wndclass.hInstance= hInstance;
wndclass.hIcon= LoadIcon(hInstance, IDI_APPLICATION);
wndclass.hCursor= LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName= NULL;
wndclass.lpszClassName= szWindowClass ;
wndclass.hIconSm= LoadIcon(wndclass.hInstance,IDI_APPLICATION);
return RegisterClassEx(&wndclass);
}
//函数:InitInstance
//作用:创建窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//函数:WndProc
//作用:处理主窗口消息
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HANDLE font2; //指向字体1的句柄
static HANDLE font1; //指向字体1的句柄
LOGFONT LogFont; //用于定义逻辑字体
HDC hdc;
PAINTSTRUCT ps; //记录窗口重画区域
switch (message)
{
case WM_CREATE: //处理窗口创建的消息
memset(&LogFont,0,sizeof(LOGFONT)); //初始化字体
LogFont.lfHeight=25; //设定字体属性
LogFont.lfWidth=15;
LogFont.lfUnderline=1;
LogFont.lfItalic=1;
lstrcpy(LogFont.lfFaceName,"Helv"); //定义字体名称
font1=CreateFontIndirect(&LogFont); //创建字体
memset(&LogFont,0,sizeof(LOGFONT));//初始化字体
LogFont.lfHeight=25; //设定字体属性
LogFont.lfWidth=15;
LogFont.lfUnderline=1;
LogFont.lfItalic=1;
lstrcpy(LogFont.lfFaceName,"Tms Rmn");//定义字体名称
font2=CreateFontIndirect(&LogFont); //创建字体
return 0;
case WM_PAINT: //处理窗口重画消息
hdc=BeginPaint(hWnd,&ps); //取得设备描述表句柄
SelectObject(hdc,font1);//选定字体font1
TextOut(hdc,20,20,"Hello!",6);//输出文本信息
SelectObject(hdc,font2); //选定字体font2
TextOut(hdc,20,120,"Hello!",6); //输出文本信息
EndPaint(hWnd,&ps);
return 0;
case WM_DESTROY: //处理销毁窗口消息
DeleteObject(font1);
DeleteObject(font2);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);//缺省消息处理
}
return 0;
}
例程的消息处理程序 WndProc函数中,处理WM_CREATE消息时,首先定义了两种 字体,在处理 WM_PAINT消息时再用这两种字体 进行文本输出。
处理WM_CREATE消息的程序段如下:
case WM_ CREATE:
memset(&LogFont,0,sizeof(LOGFONT));
LogFont.lfHeight=25; // 定义字体高度
LogFont.lfWidth=15; // 定义字体宽度
LogFont.lfUnderline=l;//字体有下划线
LogFont.lfItalic=l; // 斜体
Lstrcpy(LogFont.lfFaceName,”Helv”);
font1=CreateFontIndirect(&LogFont);
//创建字体1
memset(&LogFont,0,sizeof(LOGFONT));
//初始化字体
LogFont.lfHeight=25; //设定字体高度
LogFont.lfWidth=15; //设定字体宽度
LogFont.lfUnderline=1; //字体有下划线
LogFont.lfItalic=1; //字体为斜体
lstrcpy(LogFont.lfFaceName,"Tms Rmn");//定义字体名称
font2=CreateFontIndirect(&LogFont); //创建字体2
return 0;
以上程序中通过对LogFont结构体的各个域设定不同的值,定义了两种不同的字体font1和font2。 程序中首先使用到memset函数,memset 函数的功能是将一个字符缓冲区用一整 数值填充。
memset函数的原型定义如下:
void memset(void *dest, // 字符缓冲区指针
int c, // 填充缓冲区的整数值
size_t count // 填充次数计数
);
该函数在程序中的作用是将LogFont变量的各个域赋值为零,初始化LogFont变量。LogFont变量是LOGFONT结构的一个结构体变量,可以用于保存字体属性。
LOGFONT结构的具体定义如下:
Typedef struct tagLOGFONT // If
LONG lfHeight;// 字符高度
LONG ltWidth;// 字符宽度
LONG lfEscapement;//字符旋转角度
LONG lfOrientaion;// 字符与基线的夹角
LONG lfWeight; // 字符黑度
BYTE lfItalic; // 是否斜体
BYTE lfUnderline; // 是否带下划线
BYTE lfSrikeOut;// 非零时为删除钱字体
BYTE lfCharSet;// 字符集
BYTE lfOutPreciston;// 输出精度
BYTE lfClipPrecision; //剪切精度
BYTE lfQuality //输出质量控制
BYTE lfPitchAndFamily;//字符间距和字符族
TCHAN lfFaceName[LF_FACESIZE];//引用名
}LOGFONT;
程序中通过设定LogFont变量中各个域的不同值来定义不同的字体 。其中字体名称的设定是通过调用lstrcpy函数来完成的。
Lstrcpy函数可以实现复制字符串的功能,
其原型定义如下:
LPTSTR lstrcpy(LPTSTR lpString1,//字符缓冲区指针
LPCTSTR lpString2 //指向需要复制的字符串的指针
);
所有设定完成后,可以调用 CreateFontIndirect函数来创建字体。
执行结果如图 :