# Windows字体大小
##
* [ ] 问题的由来
>在早期的Windows中,系统字体是一种等宽字体,所有的字符的宽度都是一样的,就像早期的打字机那样。但是从Windwos3.0开始,系统字体变成了变宽字体:每个字符的宽度是不一样的,例如W要比i宽。很多相关的阅读研究表明,用变宽字体印刷的文章比用等宽字体印刷的可读性更强。其原理是当字符排列的更紧凑时,眼睛和大脑更容易注意到单词而不仅仅是一个个的字符。可想而知,从等宽字体到变宽字体导致很多Windows程序不再适用,程序员们需要学习使用字体的新技术。
> 系统字体是一种“点阵字体”:每个字符串由像素点构成。在某种程度上,系统字体中字符的大小取决于显示器的大小:字体的设计要求能够在显示器上起码显示25行80列字符。
* [ ] 字符大小
既然Windows系统字体变成了变宽字体,那么如何确定字体的高度和宽度呢,这个值是多少呢?答案是:这取决于显示器的分辨率。在不同的系统分辨率下用户还可以选择不同的系统字体。程序可以通过GetTextMetrics函数来获取当前选定的字体信息。
获取字号时,首先要获取设备环境句柄,然后调用GetTextMetrics:
hdc =GetDc(hwnd);
GetTextMetrics(hdc,&tm);
ReleaseDc(hwnd,hdc);
这里的&tm 是一个指针,指针指向了一个结构:TEXTMETRIC,该结构有20个字段。但是我们只关心其中的前7个字段:
```
typedef struct tagTEXTMETRIC { // tm
LONG tmHeight; //字符高度
TEXTMETRIC结构字段的图示
TEXTMETRIC结构字段的图示 \[1\]
LONG tmAscent; //字符上部高度(基线以上)
LONG tmDescent; //字符下部高度(基线以下)
LONG tmInternalLeading, //由tmHeight定义的字符高度的顶部空间数目
LONG tmExternalLeading, //夹在两行之间的空间数目
LONG tmAveCharWidth, //平均字符宽度
LONG tmMaxCharWidth, //最宽字符的宽度
LONG tmWeight; //字体的粗细轻重程度
LONG tmOverhang, //加入某些拼接字体上的附加高度
LONG tmDigitizedAspectX, //字体设计所针对的设备水平方向
LONG tmDigitizedAspectY, //字体设计所针对的设备垂直方向
BCHAR tmFirstChar; //为字体定义的第一个字符
BCHAR tmLastChar; //为字体定义的最后一个字符
BCHAR tmDefaultChar; //字体中所没有字符的替代字符
BCHAR tmBreakChar; //用于拆字的字符
BYTE tmItalic, //字体为斜体时非零
BYTE tmUnderlined, //字体为下划线时非零
BYTE tmStruckOut, //字体被删去时非零
BYTE tmPitchAndFamily, //字体间距(低4位)和族(高4位)
BYTE tmCharSet; //字体的字符集
} TEXTMETRIC;
```
在TEXTMETRIC结构中有设备环境中当前字体的各种信息。但字体的纵向尺寸仅由其中的5项决定,如图所示:
![](https://box.kancloud.cn/f318e6338f7ac48401cb036174a58b7a_711x478.jpg)
字体宽度:TEXTMETRICS结构中有两个字段描述了字符的宽度:tmAveCharWidth是小写字符的加权平均宽度,tmMaxCharWidth 是字体中最宽的字符的宽度。在等宽字体中,这两个值是一样的。
注意:系统字体的尺寸取决于Windows运行是的显示分辨率,有时还取决于用户选定的系统字号。Windowsti提供了与设备无关的图形界面,但是作为程序员需要注意:不要再程序中猜测文本的尺寸,不要使用固定值,应该通过调用GetTextMetrics函数来获取这些信息。
通常大写字符的平均宽度,按照tmAveCharWidth的1.5倍计算。