中年人学C语言Windows程序设计,3 文本的输出TextOut
函数功能
TextOut 函数使用当前选择的字体、背景颜色和文本颜色,将一个字符串绘制于窗口的指定位置。
API 函数原型:
注释:In 说明该参数是输入的,opt 说明该参数是可选参数。
BOOL TextOut(_In_ HDC hdc,_In_ int nXStart,_In_ int nYStart,_In_ LPCTSTR lpString,_In_ int cchString
);
参数解析
返回值
-
如果函数调用成功,返回值为非 0;
-
如果函数调用失败,返回值为 0。
TEXTMETRIC 结构
TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。
TEXTMETRIC 结构成员的值的单位取决于设备环境中当前选定的映射模式,默认的映射模式是 MM_TEXT,所以它们的值是以像素为单位的。
结构原型
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;
成员解析
成员 含义
tmHeight 字符高度(tmAscent + tmDescent)
tmAscent 字符上部高度(基线以上)
tmDescent 字符下部高度(基线以下)
tmInternalLeading 内部间距(包含在 tmHeight 中),该间距通常被用于显示重音符号
tmExternalLeading 外部间距,这个值是字体设计者建议在两行文字间留出的空间大小
tmAveCharWidth 1. 字体中小写字符的平均宽度(一般定义为字母 x 的宽度)
2. 字体中大写字符的平均宽度一般是该值的 1.5 倍计算
3. 此值不包括字体所需要的加粗和倾斜字符
tmMaxCharWidth 字体中最宽字符的宽度
tmWeight 字体的粗细轻重程度
tmOverhang 加入某些拼接字体上的附加高度
tmDigitizedAspectX 字体设计所针对的设备水平方向
tmDigitizedAspectY 字体设计所针对的设备垂直方向
tmFirstChar 为字体定义的第一个字符
tmLastChar 为字体定义的最后一个字符
tmDefaultChar 字体中所没有字符的替代字符
tmBreakChar 定义文本对齐截断操作所显示的字符
tmItalic 如果该值非零,则为斜体字体
tmUnderlined 如果该值非零,则为带下横线字体
tmStruckOut 如果该值非零,则为带删除线字体(字符中间画一条线)
tmPitchAndFamily 1. 如果低位为 0,表示等宽字体,小写和大写字母平均宽度一样
2. 如果低位为 1,表示变宽字体,大写字母是小写平均宽度的 3/2 倍
tmCharSet 字体的字符集
实例与代码
编写代码
打印10行的文本输出,从最上角开始输出第一行,然后逐行显示,每行前面带行号,后面输出字符串。
/* -------------------------------------------------------------------中年人学C语言Windows程序设计
--------------------------------------------------------------------*/#include <windows.h>
#include<strsafe.h>LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
//主函数
// 四个参数:
//hInstance : 程序当前实例的句柄(handle to current instance),以后随时可以用GetModuleHandle(0)来获得
//hPrevInstance : 前一个实例的句柄(handle to previous instance),在Win32中,每一个进程都有一个独立的4G地址空间,从0到2G属于进程私有,对其他进程来说是不可见的。所以,在Win32中,hPrevInstance总是为NULL。
//szCmdLine : 指向以 / 0结尾的命令行,不包括EXE本身的文件名(pointer to command line),以后随时可以用GetCommandLine()来获取完整的命令行。
//iCmdShow : 指明应该以什么方式显示主窗口(show state of window)。
{static TCHAR szAppName[] = TEXT("MyWindows");HWND hwnd;//句柄MSG msg;//消息WNDCLASS wndclass;//定义窗口类结构//HBRUSH hRedBrush = CreateSolidBrush(RGB(200, 200, 200));//结构成员:wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口类型wndclass.lpfnWndProc = WndProc; //窗口过程(必须是回调函数)wndclass.cbClsExtra = 0;//预留的额外空间,一般为0wndclass.cbWndExtra = 0;//预留的额外空间,一般为0wndclass.hInstance = hInstance;//应用程序的实例句柄wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//为所有基于该窗口类的窗口设定一个图标wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//为所有基于该窗口类的窗口设定一个鼠标指针wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//指定窗口背景色//wndclass.hbrBackground = hRedBrush;//指定窗口背景色wndclass.lpszMenuName = NULL; //指定窗口菜单wndclass.lpszClassName = szAppName; //指定窗口类名//注册窗口类if (!RegisterClass(&wndclass))/* RegisterClass:注册在随后调用CreateWindow函数和CreateWindowEx函数中使用的窗口类。参数为lpWndClass,指向一个WNDCLASS结构的指针返回值:ATOM的宏定义typedef WORD ATOM;typedef unsigned short WORD;关于RegisterClassEx:参数lpwcx指向一个WNDCLASSEX结构的指针如果函数成功,返回这个窗口类型的标识号;如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。*/{MessageBox(NULL, TEXT("这个程序需要在Windows系统执行!"), szAppName, MB_ICONERROR);return 0;}//实例化创建窗口hwnd = CreateWindow(szAppName,// 窗口类名称TEXT("中年人学C语言Windows程序设计"),// 窗口标题WS_OVERLAPPEDWINDOW | WS_HSCROLL| WS_VSCROLL,// 窗口风格,或称窗口格式//WS_TILEDWINDOW| WS_DLGFRAME,// 窗口风格,或称窗口格式CW_USEDEFAULT,// 初始 x 坐标CW_USEDEFAULT, // 初始 y 坐标CW_USEDEFAULT,// 初始 x 方向尺寸CW_USEDEFAULT,// 初始 y 方向尺寸NULL,// 父窗口句柄NULL,// 窗口菜单句柄hInstance,// 程序实例句柄NULL);// 创建参数/*_In_说明该参数是输入的,_opt_说明该参数是可选参数函数成功返回窗口句柄,否则返回NULL*///显示窗口ShowWindow(hwnd, iCmdShow);/* 第一次调用时应使用WinMain的参数nCmdShow作为参数如果窗口之前可见,则返回非0否则返回0*///更新窗口UpdateWindow(hwnd);/* 绕过消息队列直接向窗口过程发送WM_PAINT消息函数调用成功返回非0*///消息循环while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}/*作用:从当前线程的消息队列里取出一个消息并放入MSG结构中,不能获得其他线程的消息若消息队列为空,函数会一直等待到有消息到来才有返回值返回值:函数出现错误则返回 - 1,获得WM_QUIT消息返回0否则返回非0*/return msg.wParam;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
//回调函数
//参数:
//hwnd : 窗口句柄
//message : 消息ID
//wParam和lParam:消息参数
{HDC hdc;PAINTSTRUCT ps; //PAINTSTRUCT 结构包含一些窗口过程用来对客户区进行绘制的信息。//RECT rect;//RECT 结构定义了一个矩形的左上角和右下角的坐标。TCHAR szBuffer[128];int i;size_t iLength;TEXTMETRIC tm;//TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。static int cxChar, cHeighChar;switch (message){case WM_CREATE://获得当先hdc,的字体大小和高度hdc = GetDC(hwnd);GetTextMetrics(hdc,&tm);//GetTextMetrics 函数将当前字体的信息填充到指定缓冲区cxChar = tm.tmAveCharWidth;//字体中小写字符的平均宽度(一般定义为字母 x 的宽度)//cHeighChar = tm.tmHeight + tm.tmExternalLeading;cHeighChar = tm.tmHeight ;//字符高度(tmAscent + tmDescent)ReleaseDC(hwnd, hdc);return 0;case WM_PAINT://绘制用户区内的文字hdc = BeginPaint(hwnd, &ps);//BeginPaint 函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。//GetClientRect(hwnd, &rect);//GetClientRect 函数用于获取窗口客户区的坐标,客户区坐标指定客户区的左上角和右下角。DrawText 函数在指定的矩形里写入格式化的正文,根据指定的方法对正文格式化(扩展的制表符,字符对齐、折行等)。//DrawText(hdc, TEXT("大家好,这是我的第一个Windows窗口程序!"), -1, &rect,// DT_SINGLELINE | DT_CENTER | DT_VCENTER); for (i = 0; i < 10; i++){StringCchPrintf(szBuffer,128, TEXT("第%d行:%s"), i+1, TEXT("文本输出实例"));//StringCchPrintf 函数用于把数据格式化写入到指定的缓冲区里,该函数要求提供目标缓冲区的大小,确保不会发生越界访问。StringCchLengthW(szBuffer, 128, &iLength);//StringCchLength 函数用于确定字符串是否超过了规定的长度,以字符为计算单位。TextOut(hdc, cxChar, i* cHeighChar, szBuffer, iLength);//TextOut 函数使用当前选择的字体、背景颜色和文本颜色,将一个字符串绘制于窗口的指定位置。} EndPaint(hwnd, &ps);return 0;case WM_CLOSE://关闭窗口操作,弹出对话框,进行确认if (MessageBox(hwnd, TEXT("是否关闭程序"), TEXT("关闭确认提示"), MB_YESNO) == IDYES)DestroyWindow(hwnd);elsereturn 0;case WM_LBUTTONDOWN://鼠标按下操作,弹出信息框MessageBox(hwnd, TEXT("鼠标点击"), TEXT("弹出窗口"), MB_OK | MB_ICONINFORMATION);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);
}