【Windows编程】系列第三篇:文本字符输出
2019独角兽企业重金招聘Python工程师标准>>>
上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符。
在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接口(GDI)进行的,Windows的三大核心组件之一的GDI32.dll封装了所有的文本和图像输出。
GDI基本知识
Windows下要绘图和输出文本,都是通过GDI(Graphics Device Interface,图形设备接口)完成的,GDI是windows在绘制图文时的设备上下文环境,包括画笔、画刷、字体、位图等多种与绘制有关的对象。设备环境(DC)在绘制中起至关重要的作用。几乎所有的绘制(包括图形和文本)都与设备环境相关,注意“环境”的意义,就跟我们在画布上绘画和写字一样,绘制时的画布是哪个,用的什么笔,什么颜色,填充整个画布时用的什么刷子等等,这就是我们的绘制时的环境,而Windows绘图的DC设备上下文就是一样的道理。设备环境句柄(HDC)就是用来描述DC的句柄,可以说,只要有了这个句柄,就具备了在窗口上输出图形和文本的条件。你获得了窗口客户区的HDC,就可以在窗口客户区上画;你获得了窗口的非客户区HDC,就可以在它上面画;你获得了桌面HDC,就可以直接在桌面上画……
获取设备环境句柄的方法有两种:一是处理WM_PAINT消息时,通过BeginPaint函数返回。另外一种就是通过GetDC、GetWindowDC的API函数获取。
通过WM_PAINT消息获取DC
Windows在检测到需要重新绘制或者刷新窗口时,会主动要求处理WM_PAINT消息。比如在如下情况下就会主动求处理:
用户移动一个窗口,导致原来被盖住的部分窗口显示出来。
用户调整窗口的大小,并且窗口风格类型设置为CS_HREDRAW和CS_VREDRAW。
程序调用ScrollWindow或者ScrollDC函数滚动客户区。
程序调用InvalidateRect或者InvalidateRgn函数,该函数显示生产一条WM_PAINT消息。
我们可以在该消息中完成图文绘制,该消息的处理具有特定的格式,必须在实际绘制前调用BeginPaint,在绘制完成后调用EndPaint函数,也就是说我们需要把所有绘制的功能都放到这两个函数之间,并且HDC也只能在这之间使用,不能保存起来在其它地方使用。使用WM_PAINT有一个好处,就是windows会自己计算哪些区域需要更新,也就是说只有真正变化的地方才会更新,这样更新的代价会降低到最小。
通过API函数获取HDC
我们还可以通过GetDC、GetWindowDC函数来获取HDC,但是要注意,通过这个来获取的HDC,可以保存起来在其它时候使用,但是要记住一旦窗口有更新,必须想办法重新绘制,否则就会消失了。最后在使用完毕后需要调用ReleaseDC来释放,否则会造成资源泄露。
创建特定字体
我们平时最常见的文本输出是不需要自己创建字体的,因为常见的对象都有系统预定义好的。如果想输出点特殊(非系统预定义的)字体,就需要我们创建并自动选入设备环境。创建字体主要有CreateFont和CreateFontIndirect,这两个函数的参数都很多,基本一样,具体用法看后面的实例。
实现文本绘制
有了上面的基础,我们就可以通过Windows的API来完成文本输出了,常用的文本输出函数有TextOut、DrawText、DrawTextExt、ExtTextOut等,这些函数基本都有相似的参数,比如hdc,坐标位置,字符串。下面TextOut、DrawText、ExtTextOut为例来说明如何在Windows窗口中如何输出文本,其它请查看MSDN的用法。
#include <windows.h>
#include <tchar.h>static TCHAR szAppName[] = TEXT("Textout");
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);int WINAPI 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 program requires Windows NT!"), szAppName, MB_ICONERROR);return 0;}hWnd = CreateWindow(szAppName, // window class nameszAppName, // window captionWS_OVERLAPPEDWINDOW, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y position400, // initial x size300, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(hWnd, iCmdShow);UpdateWindow(hWnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{HDC hDC;PAINTSTRUCT ps;switch (message){case WM_CREATE:return 0;case WM_PAINT:{RECT rect = {10, 30, 100, 50};TCHAR str[] = TEXT("English and 中文");hDC = BeginPaint(hWnd, &ps);TextOut(hDC, 10, 10, str, _tcslen(str));SetTextColor(hDC, RGB(255,0,0));DrawText(hDC, str, -1, &rect, DT_LEFT|DT_VCENTER);SetTextColor(hDC, RGB(0,255,0));INT dx[] = {8,8,8,8,16,8,8,8,16,8,8,8,10};ExtTextOut(hDC, 10, 50, 0, &rect, str, _tcslen(str), dx);SetTextColor(hDC, RGB(0,0,255));rect.right = 110;rect.top = 70;rect.bottom = 82;ExtTextOut(hDC, 10, rect.top, ETO_CLIPPED, &rect, str, _tcslen(str), dx);HFONT hFont = CreateFont(96, // nHeight, 所创建字体的字符高度0, // nWidth, 字体的字符平均宽度200, // nEscapement, 字符输出方向与水平向右的方向所成角度,以0.1度为单位0, // nOrientation, 字符与基线的角度,以0.1度为单位FW_BOLD, // nWeight, 字符颜色的深浅度TRUE, // bItalic, 斜体属性标志(FALSE:正常字体,TRUE:斜体)FALSE, // bUnderline, 下划线属性标志(FALSE:无下划线,TRUE:有下划线)FALSE, // cStrikeOut, 删除线属性标志(FALSE:无删除线,TRUE:有删除线)ANSI_CHARSET, // nCharSet, 字符集标识0:ANSI字符集,1:系统缺省字符集OUT_DEFAULT_PRECIS, // nOutPrecision, 输出精度CLIP_DEFAULT_PRECIS, // nClipPrecision, 剪切精度DEFAULT_QUALITY, // nQuality, 输出品质DEFAULT_PITCH|FF_SWISS, // nPitchAndFamily, 字符间距TEXT("Arial")); // lpszFacename, 现有系统TrueType字体名称HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);SetBkMode(hDC, TRANSPARENT);SetTextColor(hDC, RGB(0x00, 0xFF, 0xFF));TextOut(hDC, 0, 150, TEXT("创建Font"), 6);DeleteObject(hFont);EndPaint(hWnd, &ps);}return 0;case WM_DESTROY:PostQuitMessage(0);return 0 ;}return DefWindowProc (hWnd, message, wParam, lParam);
}
程序运行,点击鼠标左键后效果如下:
程序中的DrawText、ExtTextOut能设置文本输出的矩形范围,超出部分是看不见的,从运行结果我们也可以看出有两行显示不全,就是由于设置的显示范围小的缘故。
另外ExtTextOut函数还可以设置字符的间距,运行结果的第三行就是这种自己设置间距不一样的结果。
本程序还用CreateFont函数创建了一个斜体、右上排列的文本串。通过上例,我们把常用的文本输出作为实例展示给大家,只要好好对照实例代码,在结合MSDN的说明,再加上本系列的第一篇的Windows编程基本框架,一定可以掌握好Windows编程的基本文本输出。
更多经验交流可以加入Windows编程讨论QQ群:454398517。
关注微信公众平台:程序员互动联盟(coder_online),你可以第一时间获取原创技术文章,和(java/C/C++/Android/Windows/Linux)技术大牛做朋友,在线交流编程经验,获取编程基础知识,解决编程问题。程序员互动联盟,开发人员自己的家。
转载请注明出处,谢谢合作!
转载于:https://my.oschina.net/u/2336532/blog/470870
【Windows编程】系列第三篇:文本字符输出相关推荐
- 【Windows 问题系列第 2 篇】如何让显示的窗口在桌面的最上面,而不被其它窗口遮挡?
这是[Windows 问题系列第 2 篇],如果觉得有用的话,欢迎关注专栏. 有时候我们打开了一窗口,比如文本框 ,里面记了一些数据,但是一点其它窗口,要么文本框被其它窗口遮挡,要么直接就最小化了. ...
- 汇川技术小型PLC梯形图编程系列教程(三):PLC系统程序与用户程序介绍
原文链接:汇川技术小型PLC梯形图编程系列教程(三):PLC系统程序与用户程序介绍 PLC的定义 可编程逻辑控制器是种专门为在工业环境下应用而设计的数字运算操作电子系统.它采用一种可编程的存储器,在其 ...
- 第三篇:字符编码、数据类型
#第三篇:字符编码.数据类型 ##3.1字符编码介绍 一.什么是字符编码 计算机要想工作必须通电,即用'电'驱使计算机干活,也就是说'电'的特性决定了计算机的特性.电的特性即高低电平(人类从逻辑上将二 ...
- javascript面向对象系列第三篇——实现继承的3种形式
前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.开宗明义,继承是指在原有对象的基础上,略作修改,得到一个新的对象.javascript主要包括类式继承.原型继承和拷贝继承这三种 ...
- 【Windows 问题系列第 7 篇】电脑卡跟C盘容量有关系吗?
这是[Windows 问题系列第 7 篇],如果觉得有用的话,欢迎关注专栏. 你有没有遇到过这样的情况? 你电脑最近很卡,然后你请教一个懂点电脑常识的同事帮你看,他过来一看,然后说,你C盘容量就剩下3 ...
- 【Windows 问题系列第 14 篇】如何删除 Win10 系统自带的微软拼音输入法
这是[Windows 问题系列第 14 篇],如果觉得有用的话,欢迎关注专栏. 第一步:点击任务栏上的输入法图标,在弹出的窗口中选择[语言首选项] 第二步:在弹出的窗口中,依下图所示,按顺序点击两个按 ...
- 【Windows 问题系列第 3 篇】Win10 系统如何打开/关闭护眼模式
这是[Windows 问题系列第 3 篇],如果觉得有用的话,欢迎关注专栏. win10 提供了一种保护视力的模式(护眼模式),一般设置窗口颜色为豆沙绿,可以降低长时间工作时电脑对眼睛造成的疲劳感. ...
- 【Windows 问题系列第 4 篇】如何更改电脑桌面文件夹路径?
这是[Windows 问题系列第 4 篇],如果觉得有用的话,欢迎关注专栏. 电脑默认的桌面路径一般都在 C 盘,而我们又特别喜欢把文件都放在桌面,因为桌面既方便又好找. 可时间久了,桌面文件会越来越 ...
- 深入理解javascript作用域系列第三篇
前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇--声明提升(hois ...
- .NET Windows编程系列笔记(一)
1._.NET Windows编程系列课程(1):.NET Windows编程概述 小结: Visual C# 2005 新增功能 • 代码段:通过提供可填写的模板,代码段加速了通用代码构造的输入.代 ...
最新文章
- 谈一谈git和SVN两大版本管理工具。
- 如何使用jQuery创建“请稍候,正在加载...”动画?
- 一台机器上运行多个ActiveMq
- (3.2)将分词和去停用词后的评论文本基于“环境、卫生、价格、服务”分类...
- 浅谈C#更改令牌ChangeToken
- 【PL/SQL】学习笔记 (1)一个简单的PL/SQL程序
- OPPO 推出 10 亿引力计划,全力构建智能化服务生态
- 阐述沙盒游戏的历史和理论
- java dwg转pdf_java实现CAD图纸文件DWG格式转为PDF格式
- Enterprise Architect安装包及教程
- java workflow 教程_学习(史帝芬)osworkflow入门教程后的一些体会
- Java poi 导出excel 设置将整个工作表打印在一页 打印机设置
- 目前使用计算机的内存和外存,简述计算机内存和外存区别及常用外存有哪些
- 这一年,熬过许多夜,也有些许收获 | 2022年终总结
- 商汤科技43篇论文横扫2017全球顶级视觉学术会议 实习生摘得五项世界冠军
- android 国产手机6.0适配(小米)
- 响应式织梦模板工业机械设备类网站
- android教程丿it教程网,[IT教程吧-www.itjc8.com]_Da类android视频
- 【工作交接】 Touch Screen 模拟按键实现
- FX3U控制松下服务器位置不准,三菱FX3UPLC如何控制松下伺服_.docx