五、GDI映像方式—MM_ANISOTROPIC:根据需要放缩图像
在MM_ISOTROPIC映像方式下设定窗口和视端口范围时,Windows会调整范围,以便两条轴上的逻辑单位具有相同的实际尺度。在MM_ANISOTROPIC映射方式下,Windows不对您所设定的值进行调整,这就是说,MM_ANISOTROPIC不需要维持正确的纵横比。
使用MM_ANISOTROPIC的一种方法是对显示区域使用任意坐标,就像我们对MM_ISOTROPIC所做的一样。下面的程序代码将点(0,0)设定为显示区域的左下角,x轴和y轴都从0到32,767:
SetMapMode (hdc, MM_ANISOTROPIC) ; SetWindowExtEx (hdc, 32767, 32767, NULL) ; SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ; SetViewportOrgEx (hdc, 0, cyClient, NULL) ;
在MM_ISOTROPIC方式下,相似的程序代码导致显示区域的一部分在轴的范围之外。但是对于MM_ANISOTROPIC,不论其尺度多大,显示区域的右上角总是(32767, 32767)。如果显示区域不是正方形的,则逻辑x和y的单位具有不同的实际尺度。
前一节在MM_ISOTROPIC映像方式下,我们讨论了在显示区域中画一个类似时钟的图像,x和y轴的范围都是从-1000到+1000。对于MM_ANISOTROPIC,也可以写出类似的程序:
SetMapMode (hdc, MM_ANISOTROPIC) ; SetWindowExtEx (hdc, 1000, 1000, NULL) ; SetViewportExtEx (hdc, cxClient / 2, -cyClient / 2, NULL) ; SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
与MM_ANISOTROPIC方式不同的是,这个时钟一般是椭圆形的,而不是圆形的。
另一种使用MM_ANISOTROPIC的方法是将x和y轴的单位固定,但其值不相等。例如,如果有一个只显示文字的程序,您可能想根据单个字符的高度和宽度设定一种粗刻度的坐标:
SetMapMode (hdc, MM_ANISOTROPIC) ; SetWindowExtEx (hdc, 1, 1, NULL) ; SetViewportExtEx (hdc, cxChar, cyChar, NULL) ;
当然,这里假设cxChar和cyChar分别是那种字体的字符宽度和高度。现在,您可以按字符行和列指定坐标。下面的叙述在距离显示区域左边三个字符,上边二个字符处显示文字:
TextOut (hdc, 3, 2, TEXT ("Hello"), 5) ;
如果您使用固定大小的字体时会更加方便,就像下面的WHATSIZE程序所示的那样。
当您第一次设定MM_ANISOTROPIC映像方式时,它总是继承前面所设定的映像方式的范围,这会很方便。可以认为MM_ANISOTROPIC不「锁定」范围;也就是说,它允许您任意改变窗口范围。例如,假设您想用MM_LOENGLISH映像方式,因为希望逻辑单位为0.01英寸,但您不希望y轴的值向上增加,喜欢如MM_TEXT那样的方向,即y轴的值向下增加,可以使用如下的代码:
SIZE size ;
其它行程序
SetMapMode (hdc, MM_LOENGLISH) ; SetMapMode (hdc, MM_ANISOTROPIC) ; GetViewportExtEx (hdc, &size) ; SetViewportExtEx (hdc, size.cx, -size.cy, NULL) ;
我们首先将映像方式设定为MM_LOENGLISH,然后,通过将映像方式设定为MM_ANISOTROPIC让范围可以自由改变。GetViewportExtEx取得视埠范围并放到一个SIZE结构中,然后,我们使用范围来呼叫SetViewportExtEx,只是要将y范围取反。