在使用Win32编程时,我们常常需要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接口(GDI)进行的,Windows的三大组件之一的GDI32.dll封装了所有的文本和图像输出函数。你也许会说直接用printf不就可以了吗?不错,这个确实是可以输出文本,但是这个智能用于console下的文本输出,而不能用于直接在窗口上面。要在窗口上输出文本,以下的函数都可以实现:
DrawText、DrawTextExt、ExtTextOut以及TextOut,这些函数基本都有相似的参数,比如hdc,坐标位置,字符串。下面以最常用的TextOut为例来说明如何在Windows窗口中如何输出文本,其他请查看MSDN的用法。TextOut的函数原型如下:
BOOL TextOut( HDC hdc, // handle to DC
intnXStart, // x-coordinate ofstarting position
intnYStart, // y-coordinate ofstarting position
LPCTSTRlpString, // character string
intcbString // number of characters
);
参数说明:
Hdc,设备上下文句柄,所有的窗口都会有这个句柄,最后的文本将在上面输出。
nXStart,字符串输出的开始横坐标。
nYStart,字符串输出的开始纵坐标。
lpString,要输出的字符串。
cbString,要输出的字符数目,注意是字符数而不是字节数。
在windows窗口上输出有两种方式来获取设备上下文句柄,一种是在处理WM_PAINT消息时通过BeginPaint函数获取,另外一种就是通过主动获取上下文句柄函数GetDC或者GetWindowDC,这种可以在任何时候进行输出,但是一旦窗口有更新,必须想办法重新绘制,否则就会消失了。而通过WM_PAINT绘制的文本会在窗口有更新时自动调用,因此不用担心什么时候需要重绘的问题,Windows会在以下的情况下受到WM_PAINT消息:
使用WM_PAINT还有一个好处,就是windows会自己计算哪些区域需要更新,也就是说只有真正变化的地方才会更新,这样更新的代价会降低到最小。
下面的实例中,我们用了这两种方式获取设备上下文句柄来输出文本:
#include <windows.h>
staticTCHAR szAppName[] = TEXT("HelloWin32");
staticLRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
intWINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wndclass;
// 注册窗口类
wndclass.style =CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance =hInstance;
wndclass.hIcon =LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor =LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox (NULL, TEXT("This programrequires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
//创建主窗体
hWnd = CreateWindow(szAppName, //window class name
TEXT("TextOut demo"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
400, // initialx size
300, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
//进入消息循环
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
staticLRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCTps;
static int cxClient,cyClient;
switch (message)
{
case WM_CREATE:
return 0;
case WM_SIZE:
cxClient= LOWORD(lParam);
cyClient= HIWORD(lParam);
return 0;
case WM_PAINT:
hDC= BeginPaint(hWnd, &ps);
//使用BeginPaint函数返回的句柄
TextOut(hDC,50, 50, TEXT("Hello, World!"),13);
EndPaint(hWnd,&ps);
return 0;
case WM_LBUTTONDOWN:
{
//点击鼠标左键后也执行文本输出
HDChDC = GetDC(hWnd);
//设置文本颜色
SetTextColor(hDC,RGB(0, 0xFF, 0));
//设置文本背景颜色
SetBkColor(hDC,RGB(0xFF, 0, 0));
//使用GetDC函数返回的句柄
TextOut(hDC,50, 100, TEXT("This is a test!"),15);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0 ;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
程序运行,点击鼠标左键后效果如下:
然后我们用鼠标改变窗口大小后,可以看见直接用GetDC获取设备上下文句柄画出来的文本消失了,而在处理WM_PAINT消息时通过BeginPaint函数获取设备上下文画出来的文本依然存在。
至于用DrawText、DrawTextExt、ExtTextOut这几个函数输出文本大同小异,前面两个都增加了矩形的限制。详细用法请自己参考MSDN,通过本例,您应该学会如何输出文本了。