五、GDI映像方式—MM_ISOTROPIC映像方式
如果想要在使用任意的轴时都保证两个轴上的逻辑单位相同,则MM_ISOTROPIC映像方式就是理想的映像方式。这时,具有相同逻辑宽度和高度的矩形显示为正方形,具有相同逻辑宽度和高度的椭圆显示为圆。
当您刚开始将映像方式设定为MM_ISOTROPIC时,Windows使用与MM_LOMETRIC同样的窗口和视端口范围(但是,不要对此有所依赖)。区别在于,您现在可以呼叫SetWindowExtEx和SetViewportExtEx来根据自己的偏好改变范围了,然后,Windows将调整范围的值,以便两条轴上的逻辑单位有相同的实际距离。
一般说来,您可以用所期望的逻辑窗口的逻辑尺寸作为SetWindowExtEx的参数,用显示区域的实际宽和高作为SetViewportExtEx的参数。Windows在调整这些范围时,必须让逻辑窗口适应实际窗口,这就有可能导致显示区域的一段落到了逻辑窗口的外面。必须在呼叫SetViewportExtEx之前呼叫SetWindowExtEx,以便最有效地使用显示区域中的空间。
例如,假设您想要一个「传统的」单象限虚拟坐标系,其中(0,0)在显示区域的左下角,宽度和高度的范围都是从0到32,767,并且希望x和y轴的单位具有同样的实际尺寸。以下就是所需的程序:
如果其后用GetWindowExtEx和GetViewportExtEx函数获得了窗口和视端口的范围,可以发现,它们并不是先前指定的值。Windows将根据显示设备的纵横比来调整范围,以便两条轴上的逻辑单位表示相同的实际尺寸。
如果显示区域的宽度大于高度(以实际尺寸为准),Windows将调整x的范围,以便逻辑窗口比显示区域视端口窄。这样,逻辑窗口将放置在显示区域的左边:
Windows 98不允许在显示区域的右边超越x轴的范围之外显示任何东西,因为这需要一个大于16位所能表示的坐标。Windows NT使用全32位坐标,您可以在超出右边显示一些东西。
如果显示区域的高度大于宽度(以实际尺寸为准),那么Windows将调整y的范围。这样,逻辑窗口将放置在显示区域的下边:
Windows 98不允许在显示区域的顶部显示任何东西。
如果您希望逻辑窗口总是放在显示区域的左上部,那么将前面给出的程序代码改为:
在呼叫SetWindowOrgEx中,我们要求将逻辑点(0, 32767)映像为设备点(0,0)。现在,如果显示区域的高大于宽,则坐标系将安排为:
对于时钟程序,您也许想要使用一个四象限的笛卡尔坐标系,四个方向的坐标尺度可以任意指定,(0,0) 必须居于显示区域的中央。如果您想要每条轴的范围从0到1000,则可以使用以下程序代码:
如果显示区域的宽度大于高度,则逻辑坐标系形如:
如果显示区域的高度大于宽度,那么逻辑坐标也会居中:
记住,窗口或者视端口范围并不意味着要进行剪裁。在呼叫GDI函数时,您仍然对以随便地使用小于-1000和大于1000的x和y值。根据显示区域的外形,这些点可能看得见,也可能看不见。
在MM_ISOTROPIC映像方式下,可以使逻辑单位大于图素。例如,假设您想要一种映像方式,使点(0,0)显示在屏幕的左上角,y的值向下增长(和MM_TEXT相似),但是逻辑坐标单位为1/16英寸。以下是一种方法:
SetWindowExtEx函数的参数指出了每一英寸中逻辑单位数。SetViewportExtEx函数的参数指出了每一英寸中实际单位数(图素)。
然而,这种方法与Windows NT中的度量映像方式不一致。这些映射方式使用显示器的图素大小和公制大小。要与度量映像方式保持一致,可以这样做:
在这个程序代码中,视埠范围设定为按图素计算的整个屏幕的大小,窗口范围则必须设定为以1/16英寸为单位的整个屏幕的大小。GetDeviceCaps以HORZRES和VERTRES为参数,传回以毫米为单位的设备尺寸。如果我们使用浮点数,将把毫米数除以25.4,转换为英寸,然后,再乘以16以转换为l/16英寸。但是,由于我们使用的是整数,所以先乘以160,再除以254。
当然,这种坐标系会使逻辑单位大于实际单位。在设备上输出的所有东西都将映像为按1/16英寸增量的坐标值。当然,这样就不能画两条间隔l/32英寸的水平直线,因为这样将需要小数逻辑坐标。
当您刚开始将映像方式设定为MM_ISOTROPIC时,Windows使用与MM_LOMETRIC同样的窗口和视端口范围(但是,不要对此有所依赖)。区别在于,您现在可以呼叫SetWindowExtEx和SetViewportExtEx来根据自己的偏好改变范围了,然后,Windows将调整范围的值,以便两条轴上的逻辑单位有相同的实际距离。
一般说来,您可以用所期望的逻辑窗口的逻辑尺寸作为SetWindowExtEx的参数,用显示区域的实际宽和高作为SetViewportExtEx的参数。Windows在调整这些范围时,必须让逻辑窗口适应实际窗口,这就有可能导致显示区域的一段落到了逻辑窗口的外面。必须在呼叫SetViewportExtEx之前呼叫SetWindowExtEx,以便最有效地使用显示区域中的空间。
例如,假设您想要一个「传统的」单象限虚拟坐标系,其中(0,0)在显示区域的左下角,宽度和高度的范围都是从0到32,767,并且希望x和y轴的单位具有同样的实际尺寸。以下就是所需的程序:
SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 32767, 32767, NULL) ; SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ; SetViewportOrgEx (hdc, 0, cyClient, NULL) ;
如果显示区域的宽度大于高度(以实际尺寸为准),Windows将调整x的范围,以便逻辑窗口比显示区域视端口窄。这样,逻辑窗口将放置在显示区域的左边:
如果显示区域的高度大于宽度(以实际尺寸为准),那么Windows将调整y的范围。这样,逻辑窗口将放置在显示区域的下边:
如果您希望逻辑窗口总是放在显示区域的左上部,那么将前面给出的程序代码改为:
SetMapMode (MM_ISOTROPIC) ; SetWindowExtEx (hdc, 32767, 32767, NULL) ; SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ; SetWindowOrgEx (hdc, 0, 32767, NULL) ;
对于时钟程序,您也许想要使用一个四象限的笛卡尔坐标系,四个方向的坐标尺度可以任意指定,(0,0) 必须居于显示区域的中央。如果您想要每条轴的范围从0到1000,则可以使用以下程序代码:
SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 1000, 1000, NULL) ; SetViewportExtEx (hdc, cxClient / 2, -cyClient / 2, NULL) ; SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
在MM_ISOTROPIC映像方式下,可以使逻辑单位大于图素。例如,假设您想要一种映像方式,使点(0,0)显示在屏幕的左上角,y的值向下增长(和MM_TEXT相似),但是逻辑坐标单位为1/16英寸。以下是一种方法:
SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 16, 16, NULL) ; SetViewportExtEx (hdc, GetDeviceCaps (hdc, LOGPIXELSX), GetDeviceCaps (hdc, LOGPIXELSY), NULL) ;
然而,这种方法与Windows NT中的度量映像方式不一致。这些映射方式使用显示器的图素大小和公制大小。要与度量映像方式保持一致,可以这样做:
SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 160 * GetDeviceCaps (hdc, HORZSIZE) / 254, 160 * GetDeviceCaps (hdc, VERTSIZE) / 254, NULL) ; SetViewportExtEx (hdc, GetDeviceCaps (hdc, HORZRES), GetDeviceCaps (hdc, VERTRES), NULL) ;
当然,这种坐标系会使逻辑单位大于实际单位。在设备上输出的所有东西都将映像为按1/16英寸增量的坐标值。当然,这样就不能画两条间隔l/32英寸的水平直线,因为这样将需要小数逻辑坐标。