二、Windows图形处理—设备内容(设备的大小)
假定要绘制边长为1英寸的正方形,您(程序写作者)或Windows(操作系统)需要知道视讯显示上1英寸对应多少图素。使用GetDeviceCaps函数能取得有关如视讯显示器和打印机之类输出设备的实际显示大小信息。
视讯显示器和打印机是两个不同的设备。但也许最不明显的区别是「分辨率」与设备联系起来的方式。对于打印机,我们经常用「每英寸的点数(dpi)」表示分辨率。例如,大多数激光打印机有300或600dpi的分辨率。然而,视讯显示器的分辨率是以水平和垂直的总图素数来表示的,例如,1024×768。大多数人不会告诉您他的打印机在一张纸上水平和垂直打印多少图素或他们的视讯显示器上每英寸有多少图素。
在本书中,我用「分辨率」来严格定义每度量单位(一般为英寸)内的图素数。我使用「图素大小」或「图素尺寸」表示设备水平或垂直显示的总图素数。「度量大小」或「度量尺寸」是以英寸或毫米为单位的设备显示区域的大小。(对于打印机页面,它不是整个页面,只是可打印的区域。)图素大小除以度量大小就得到分辨率。
现在Windows使用的大多数视讯显示器的屏幕都是宽比高多33%。这就表示纵横比为1.33:1或(一般写法)4:3。历史上,该比例可追溯到Thomas Edison制作电影的年代。它一直作为电影的标准纵横比,直到1953年出现各种型态的宽银幕投影机。电视机屏幕的纵横比也是4:3。
然而,Windows应用程序不应假设视讯显示器具有4:3的纵横比。人们进行文字处理时希望视讯显示器与一张纸的长和宽类似。最普通的选择是把4:3变为3:4显示,把标准显示翻转一下。
如果设备的水平分辨率与垂直分辨率相等,就称设备具有「正方形图素」。现在,Windows普遍使用的视讯显示器都具有正方形图素,但也有例外。(应用程序也不应假设视讯显示器总是具有正方形图素。)Windows第一次发表时,标准显示卡卡是IBM Color Graphics Adapter(CGA),它有640×200的图素大小;Enhanced Graphics Adapter(EGA)有640×350的图素大小;Hercules Graphics Card有720×348的图素大小。所有这些显示卡都使用4:3纵横比的显示器,但是水平和垂直图素数的比值都不是4:3。
执行Windows的使用者很容易确定视讯显示器的图素大小。在「控制台」中执行「显示器」,并选择「设定」页面标签。在标有「桌面区域」的字段中,可以看到这些图素尺寸之一:
-
640×480图素
-
800×600图素
-
1024×768图素
-
1280×1024图素
-
1600×1200图素
所有这些都是4:3。(除了1280×1024图素大小。这不但有些不好,还有些令人反感。所有这些图素尺寸都认为在4:3的显示器上会产生正方形的图素。)
Windows应用程序可以使用SM_CXSCREEN和SM_CYSCREEN参数从GetSystemMetrics得到图素尺寸。从DEVCAPS1程序中您会注意到,程序可以用HORZRES(水平分辨率)和VERTRES参数从GetDeviceCaps中得到同样的值。这里「分辨率」指的是图素大小而不是每度量单位的图素数。
这些是设备大小的简单部分,现在开始复杂的部分。
前两个设备能力,HORZSIZE和VERTSIZE,文件中称为「以毫米计的实际屏幕的宽度」及「以毫米计的实际屏幕的高度」(在/Platform SDK/Graphics和Multimedia Services/GDI/Device Contexts/Device Context Reference/Device Context Functions/GetDeviceCaps中)。这些看起来更像直接的定义。例如,给出视讯显示卡和显示器的接口特性,Windows如何真正知道显示器的大小呢?如果您有台膝上型计算机(它的视讯驱动程序能知道准确的屏幕大小)并且连接了外部显示器,又是哪种情况呢?如果把视讯投影机连接到计算机上呢?
在Windows的16位版本中(及在Windows NT中),Windows为HORZSIZE和VERTSIZE使用「标准」的显示大小。然而,从Windows 95开始,HORZSIZE和VERTSIZE值是从HORZRES、VERTRES、LOGPIXELSX和LOGPIXELSY值中衍生出来的。这是它的工作方式。
当您在「控制台」中使用「显示器」程序选择显示的图素大小时,也可以选择系统字体的大小。这个选项的原因是用于640×480显示的字体在提升到1024×768或更大时字太小,而您可能想要更大的系统字体。这些系统字体大小指「显示器」程序的「设定」页面卷标中的「小字体」和「大字体」。
在传统的排版中,字体的字母大小由「点」表示。1点大约1/72英寸,在计算机排版中1点正好为1/72英寸。
理论上,字体的点值是从字体中最高的字符顶部到例如j、p、q和y等字母下部的字符底部的距离,其中不包括重音符号。例如,在10点的字体中此距离是10/72英寸。根据TEXTMETRIC结构,字体的点值等于tmHeight字段减去tmInternalLeading字段,如图5-2所示(该图与上一章的图4-3一样)。
在真正的排版中,字体的点值与字体字母的实际大小并不正好相等。字体的设计者做出的实际字符比点值指示的要大一些或小一些。毕竟,字体设计是一种艺术而不是科学。
TEXTMETRIC结构的tmHeight字段指出文字的连续行在屏幕或打印机上间隔的方式。这也可以用点来测量。例如,12点的行距指出文字连续行的基准线应该间隔12/72(或1/6)英寸。不应该为10点字体使用10点行距,因为文字的连续行会碰到一起。
10点字体读起来很舒服。小于10点的字体不益于长时间阅读。
Windows系统字体-不考虑是大字体还是小字体,也不考虑所选择的视频图素大小-固定假设为10点字体和12点行距。这听起来很奇怪,如果字体都是10点,为什么还把它们称为大字体和小字体呢?
解答是:当您在「控制台」的「显示」程序上选择小字体或大字体时,实际上是选择了一个假定的视讯显示分辨率,单位是每英寸的点数 。当选择小字体时,即要Windows假定视讯显示分辨率为每英寸96点。当选择大字体时,即要Windows假定视讯显示分辨率为每英寸120点。
再看看图5-2。那是小字体,它依据的显示分辨率为每英寸96点。我说过它是10点字体。10点即是10/72英寸,如果乘以96点,每英寸大概就为13图素。这即是tmHeight减去tmInternalLeading的值。行距是12点,或12/72英寸,它乘以96点,每英寸就为16图素。这即是tmHeight的值。
图5-3显示大字体。这是依据每英寸120点的分辨率。同样,它是10点字体,10/72乘以120点,每英寸等于16图素,即是tmHeight减tmInternalLeading的值。12点行距等于20图素,即是tmHeight的值。(像第四章一样,再次强调所显示的是实际的度量大小,因此您可以理解它工作的方式。不要在您的程序中对此写作程序。)
在Windows程序中,您可以使用GetDeviceCaps函数取得使用者在「控制台」的「显示器」程序中选择的以每英寸的点数为单位的假定分辨率。要得到这些值(如果视讯显示器不具有正方形图素,在理论上这些值是不同的),可以使用索引LOGPIXELSX和LOGPIXELSY。LOGPIXELS指逻辑图素,它的基本意思是「以每英寸的图素数为单位的非实际分辨率」。
用HORZSIZE和VERTSIZE索引从GetDeviceCaps得到的设备能力,在文件上称为「实际屏幕的宽度,单位毫米」及「实际屏幕的高度,单位毫米」。因为这些值是从HORZRES、VERTRES、LOGPIXELSX和LOGPIXELSY值中衍生出来的,所以它们应该称为「逻辑宽度」和「逻辑高度」。公式是:
常数25.4用于把英寸转变为毫米。
这看起来是种不合逻辑的退步。毕竟,视讯显示器是可以用尺以毫米为单位的大小(至少是近似的)衡量的。但是Windows 98并不关心这个大小。相反,它以使用者选择的显示图素大小和系统字体大小为基础计算以毫米为单位的显示大小。更改显示的图素大小并根据GetDeviceCaps更改度量大小。这有什么意义呢?
这非常有意义。假定有一个17英寸的显示器。实际的显示大小大约是12英寸乘9英寸。假定在最小要求的640×480图素大小下执行Windows。这意味着实际的分辨率是每英寸53点。10点字体(在纸上便于阅读)在屏幕上从A的顶部到q的底部只有7个图素。这样的字体很难看而且不易读。(可问问那些在旧的Color Graphics Adapter上执行Windows的人们。)
现在,把您的计算机接上视讯投影机。投影的视讯显示器是4英尺宽,3英尺高。同样的640×480图素大小现在是大约每英寸13点的分辨率。在这种条件下试图显示10点的字体是很可笑的。
10点字体在视讯显示器上应是可读的,因为它在打印时是肯定可读的。所以10点字体就成为一个重要的参照。当Windows应用程序确保10点屏幕字体为平均大小时,就能够使用8点字体显示较小的文字(仍可读),或用大于10点的字体显示较大的文字。因而,视频分辨率(以每英寸的点数为单位)由10点字体的图素大小来确定是很有意义的。
然而,在Windows NT中,用老的方法定义HORZSIZE和VERTSIZE值。这种方法与Windows的16位版本一致。HORZRES和VERTRES值仍然表示水平和垂直图素的数值,LOGPIXELSX和LOGPIXELSY仍然与在「控制台」的「显示器」程序中选择的字体有关。在Windows 98中,LOGPIXELSX和LOGPIXELSY的典型值是96和120 dpi,这取决于您选择的是小字体还是大字体。
在Windows NT中的区别是HORZSIZE和VERTSIZE值固定表示标准显示器大小。对于普通的显示卡,取得的HORZSIZE和VERTSIZE值分别是320和240毫米。这些值是相同的,与选择的图素大小无关。因此,这些值与用HORZRES、VERTRES、LOGPIXELSX和LOGPIXELSY索引从GetDeviceCaps中得到的值不同。然而,可以用前面的公式计算在Windows 98下的HORZSIZE和VERTSIZE值。
如果程序需要实际的视讯显示大小该怎么办?也许最好的解决方法是用对话框让使用者输入它们。
最后,来自GetDeviceCaps的另三个值与视讯大小有关。ASPECTX、ASPECTY和ASPECTXY值是每一个图素的相对宽度、高度和对角线大小,四舍五入到整数。对于正方形图素,ASPECTX和ASPECTY值相同。无论如何,ASPECTXY值应等于ASPECTX与ASPECTY平方和的平方根,就像直角三角形一样。