在SDK中使用TextOut进行文字输出
2008-10-16 21:36
302 查看
=============《Windows 程序设计 第五版》读书笔记 || 第四章 输出文字 =============
这看似是一个很简单的问题,不就是进行文字的输出么,C语言里的printf ,C++里的count,都很简单的,不过这在SDK中却是件难事儿。在SDK中输出一段文字,不仅需要设置文字的颜色、字体、字体高度、字体宽度,还得设置文字的背景颜色,相比于C/C++中的文字输出,要复杂许多。要弄清在SDK中,文字是怎么显示在窗体上的,还得了解一下Windows中文字的一些细节问题。
一、系统字体
如何设置文字的颜色,在这一章中没有作介绍,默认情况下,输出文字的背景颜色是使用WNDCLASS结构中hbrBackground字段的设置,比如在写WNDCLASS窗口类时,将hbrBackground设置为灰色,那么TextOut默认输出的文字背景就是灰色的(注释:好像搞错了,即便hbrBackground为其它颜色,TextOut默认输出文字的背景颜色仍然是白色)。
先说说这个系统字体吧!
系统字体是一种「点阵字体」,也就是每个字都是用点组合而成,所谓三点成一线,这点阵字体就是这么回事儿。TextOut默认输出的是系统字体,也就是点阵字体,这个点阵字体,在“控制面板”的“字体”窗口中也能找到,我在Windows记事本中设置了名为“Courier” 的点阵字体(如图1),有点儿难看,还有“Courier New”也是一个点阵字体,字体效果跟“Courier”一个样。书上说在以前的Windows版本中,系统字体是一种等宽字体,看这点阵字体的效果,好像就是一种等宽字体。
图1
二、字符大小
弄清字符大小对我来说算是一个难点,字符大小包括字符的宽度和高度,而字符高度由五个部分组成,这咱先不说,先说说存放字符信息的结构体TEXTMETRIC。呃。。。好像不对,要弄清TEXTMETRIC结构体中的各个字段的作用,还得先说说组成字符高度的那五个部分。用图说话,先看看书中的这张图(如图2)。
图2
刚开始看这个图的时候有一些晕乎,可能是被图书的英文吓的吧!不过换了一种方法后,就恍然大悟了。咱把这一个字符看作是书中的一个页面,一个书页有页眉/正文和页脚,而tminternalLeading就是书页的页眉,不过这个tminternalLeading是放字母声调之类的东西,比如拼音中的一声调,二声调,三声调和四声调。tmAscent是书页的页眉+正文部分,最后tmDescent是书页的页脚,页眉+正文+页脚等于书页的高度,那么tmAscent+tmDescent就是字符的高度了,即tmHeight。
一个字符除了这五个组成部分之外,还有一个tmExternalLeading,书上说它是字体设计者建议加在横向字符之间的空间大小,这句话按字面来理解,那就是说tmExternalLeading是设置字符间距咯,不过根据实践证明,这是设置字符行间距的,就是上一行和下一行之间的距离,而一个字符的高度真实高度是tmHeight+tmExternalLeading,即字符本身的高度加上行间距,tmExternalLeading默认值为0。
说了字符的高度,还得说说字符的宽度,这相对简单些,我们所需要知道的就是字符的平均宽度(tmAveCharWidth)和最大宽度(tmMaxCharWidth),我不知道为什么会有字符的平均宽度,但对于等宽字符,字符的平均宽度和最大宽度是相同的。
先对上面的这部分内容作个总结,主要说了点阵字体/等宽字体和变宽字体,现在我们用的好像是TrueType 字体,是一种变宽字体,估计在第十七章中会作详细介绍。
好了,弄清楚的字体高度的组成部分,接下来就来说说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;
对于这个结构中的这些字段,我们只需要知道前面七个是啥意思就行了,而这七个字段在前面都已经解释清楚了。现在我们就可以使用GetTextMetrics函数来将字符的这些信息存放到TEXTMETRIC结构体中了:
TEXTMETRIC tm; //定义一个TEXTMETRIC结构体
GetTextMetrics(hdc, &tm);
通过断点调试,可以看到tm结构体中各个字段的值(如图3)。
图3
下面来个实例练习一下:
hdc = GetDC (hwnd) ; //获得一个设备内容句柄
GetTextMetrics (hdc, tm) ; //获得字体信息存入tm结构体
cxChar = tm.tmAveCharWidth ; //字符平均宽度
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; //这个应该是设置变宽字体的平均宽度
cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符高度
ReleaseDC (hwnd, hdc) ;
在对字符的高度和宽度进行设置后,就可以使用TextOut来输出文字了。最后准备来个完整的实例,不过还得先看看TextOut函数的几个参数,其实也挺简单的:
TextOut (hdc, x, y, psText, iLength) ;
算了,这几个参数太简单,就不解释了,来个实例代码吧,看看如何用TextOut输出多行文字。
static int cyChar; //TextOut中参数y的值
TEXTMETRIC tm; //字体信息的结构体
PAINTSTRUCT ps; //重绘区域
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading + 10 ;
ReleaseDC (hwnd, hdc) ;
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
TextOut(hdc, 0, 0, "这是第一行文字", lstrlen("这是第一行文字"));
TextOut(hdc, 0, cyChar,
"这是第二行文字", lstrlen("这是第二行文字"));
EndPaint (hwnd, &ps) ;
return 0;
这看似是一个很简单的问题,不就是进行文字的输出么,C语言里的printf ,C++里的count,都很简单的,不过这在SDK中却是件难事儿。在SDK中输出一段文字,不仅需要设置文字的颜色、字体、字体高度、字体宽度,还得设置文字的背景颜色,相比于C/C++中的文字输出,要复杂许多。要弄清在SDK中,文字是怎么显示在窗体上的,还得了解一下Windows中文字的一些细节问题。
一、系统字体
如何设置文字的颜色,在这一章中没有作介绍,默认情况下,输出文字的背景颜色是使用WNDCLASS结构中hbrBackground字段的设置,比如在写WNDCLASS窗口类时,将hbrBackground设置为灰色,那么TextOut默认输出的文字背景就是灰色的(注释:好像搞错了,即便hbrBackground为其它颜色,TextOut默认输出文字的背景颜色仍然是白色)。
先说说这个系统字体吧!
系统字体是一种「点阵字体」,也就是每个字都是用点组合而成,所谓三点成一线,这点阵字体就是这么回事儿。TextOut默认输出的是系统字体,也就是点阵字体,这个点阵字体,在“控制面板”的“字体”窗口中也能找到,我在Windows记事本中设置了名为“Courier” 的点阵字体(如图1),有点儿难看,还有“Courier New”也是一个点阵字体,字体效果跟“Courier”一个样。书上说在以前的Windows版本中,系统字体是一种等宽字体,看这点阵字体的效果,好像就是一种等宽字体。
图1
二、字符大小
弄清字符大小对我来说算是一个难点,字符大小包括字符的宽度和高度,而字符高度由五个部分组成,这咱先不说,先说说存放字符信息的结构体TEXTMETRIC。呃。。。好像不对,要弄清TEXTMETRIC结构体中的各个字段的作用,还得先说说组成字符高度的那五个部分。用图说话,先看看书中的这张图(如图2)。
图2
刚开始看这个图的时候有一些晕乎,可能是被图书的英文吓的吧!不过换了一种方法后,就恍然大悟了。咱把这一个字符看作是书中的一个页面,一个书页有页眉/正文和页脚,而tminternalLeading就是书页的页眉,不过这个tminternalLeading是放字母声调之类的东西,比如拼音中的一声调,二声调,三声调和四声调。tmAscent是书页的页眉+正文部分,最后tmDescent是书页的页脚,页眉+正文+页脚等于书页的高度,那么tmAscent+tmDescent就是字符的高度了,即tmHeight。
一个字符除了这五个组成部分之外,还有一个tmExternalLeading,书上说它是字体设计者建议加在横向字符之间的空间大小,这句话按字面来理解,那就是说tmExternalLeading是设置字符间距咯,不过根据实践证明,这是设置字符行间距的,就是上一行和下一行之间的距离,而一个字符的高度真实高度是tmHeight+tmExternalLeading,即字符本身的高度加上行间距,tmExternalLeading默认值为0。
说了字符的高度,还得说说字符的宽度,这相对简单些,我们所需要知道的就是字符的平均宽度(tmAveCharWidth)和最大宽度(tmMaxCharWidth),我不知道为什么会有字符的平均宽度,但对于等宽字符,字符的平均宽度和最大宽度是相同的。
先对上面的这部分内容作个总结,主要说了点阵字体/等宽字体和变宽字体,现在我们用的好像是TrueType 字体,是一种变宽字体,估计在第十七章中会作详细介绍。
好了,弄清楚的字体高度的组成部分,接下来就来说说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;
对于这个结构中的这些字段,我们只需要知道前面七个是啥意思就行了,而这七个字段在前面都已经解释清楚了。现在我们就可以使用GetTextMetrics函数来将字符的这些信息存放到TEXTMETRIC结构体中了:
TEXTMETRIC tm; //定义一个TEXTMETRIC结构体
GetTextMetrics(hdc, &tm);
通过断点调试,可以看到tm结构体中各个字段的值(如图3)。
图3
下面来个实例练习一下:
hdc = GetDC (hwnd) ; //获得一个设备内容句柄
GetTextMetrics (hdc, tm) ; //获得字体信息存入tm结构体
cxChar = tm.tmAveCharWidth ; //字符平均宽度
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; //这个应该是设置变宽字体的平均宽度
cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符高度
ReleaseDC (hwnd, hdc) ;
在对字符的高度和宽度进行设置后,就可以使用TextOut来输出文字了。最后准备来个完整的实例,不过还得先看看TextOut函数的几个参数,其实也挺简单的:
TextOut (hdc, x, y, psText, iLength) ;
算了,这几个参数太简单,就不解释了,来个实例代码吧,看看如何用TextOut输出多行文字。
static int cyChar; //TextOut中参数y的值
TEXTMETRIC tm; //字体信息的结构体
PAINTSTRUCT ps; //重绘区域
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading + 10 ;
ReleaseDC (hwnd, hdc) ;
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
TextOut(hdc, 0, 0, "这是第一行文字", lstrlen("这是第一行文字"));
TextOut(hdc, 0, cyChar,
"这是第二行文字", lstrlen("这是第二行文字"));
EndPaint (hwnd, &ps) ;
return 0;
相关文章推荐
- 在SDK中使用TextOut进行文字输出
- 在场景中输出文字--SetTextColor(),SetBkMode(),TextOut()的使用
- 使用类对时间进行输出
- 使用VMware VSphere WebService SDK进行开发 (三)——获取主机(HostSystem)的基本信息
- 使用C#调用PI-SDK进行基于PI的开发——使用PI-SDK建立与PI数据库的连接(转载)
- 使用Java的代理机制进行日志输出(存疑)
- Windows SDK程序的输出文字和格式控制(wsprintf、swprintf、Textout)
- 使用BO JAVA SDK打开WEBI报表,并进行PDF、EXCEL、CSV、HTML导出
- Kinect2.0之使用KinectSDK自带的KinectStudio进行数据采集
- 使用IExport进行图片输出出现File creation error
- 数组的创建/查找数组里面的内容/添加数组中元素/使用指定的字符串把数组链接起来/判断数组内是否有指定的数组元素/四种遍历进行输出数组中的元素有哪些
- 学习中---在SVG中使用滤镜效果和输出文字(转载)
- GUI界面中使用printf进行输出调试
- 使用CodeIgniter来调用淘宝SDK数据进行PHP开发
- 使用百度SDK进行定位完整Demo
- 使用assertEquals()对控制台println()输出进行判断失败的原因及处理
- Linux下使用xargs得到字符串作为参数进行输出、awk得到字符串作为参数进行输出
- 使用java将一个int数字进行翻转,例如32输出2
- java使用文件或字节数组方式加载图片,并修改图片后进行保存、输出等
- 简单使用dom4j对xml文件进行输出操作(如何使用dom4j对xml文件进行输出)