在本章以后的各节中将介绍其中一些设备属性,其他属性在以后章节中介绍。
3.3、设备坐标系
为在输出设备上定位和绘制图像对象,必须引入一种坐标系。Windows的各种不同类型设备所使用的坐标称为设备坐标。他们使用笛卡尔坐标系,在这些设备坐标系中,单位都以象素的个数表示(称为设备单位)。x轴上的值自左向右增加,y轴上的值自顶向下增加,见图3-1。
![]() | ||
| 图3-1 Windows的设备坐标系 |
本节以视频显示设备为例介绍Windows的设备坐标系,其中的许多内容也适合用于象打印机等硬拷贝输出设备。
在Windows环境中,视频显示设备是个共享设备,即在同一时刻,显示设备上能够同时显示多个应用程式的输出信息。为了保护一个程式显示的信息不被其他程式破坏,Windows通过将显示区看作不同的设备对象来限制应用程式输出信息的范围。
一个应用程式可获取三种不同的显示设备对象句柄,每种句柄所标识的设备对象代表屏幕上的不同区域。我们能够将这三个句柄所标识的对象视作三个不同的抽象显示设备,都带有如图3-1所示的设备坐标系,但对不同的抽象设备,坐标原点不相同的。这样,当使用相同的起始坐标而使用不同的设备对象句柄调用GetDC函数(例如TextOut())进行绘图时,信息显示的位置不相同。
第一抽象设备是用户区对象,他的坐标原点在用户区的左上角。定位该区域的设备坐标系称为用户区坐标系。使用函数GetDC()或BeginPaint()得到的句柄是标识用户区的句柄。当使用该句柄标识该区域的句柄作为GDI函数的参数时,GDI函数所使用的坐标值是相对于用户区坐标系。
第二个抽象设备是全窗口对象。他包括标题栏、选单、滚动杆和窗口框架等。定位这个区域的坐标系称为全窗口坐标系,他的原点的左上角。使用函数GetWindowsDC()能够获得该设备对象的句柄,然后通过该句柄使用全窗口坐标系在该区域中绘图。应用程式一般不在这个区域中绘图。
第三个抽象设备是整个屏幕对象,其坐标原点在屏幕的左上角,定位该区域的设备坐标系称为屏幕坐标系。使用语句:
HDC hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
能够获得该设备对象的句柄,使用该句柄的GDI函数所使用的坐标是相对于屏幕坐标系。
这三种坐标系方便了程式在不同的区域绘制图像的需要。例如,由于使用用户区坐标系,即使窗口在屏幕上被移动到其他位置,但用户区中显示的信息相对于用户坐标系而言其坐标值不变。
使用坐标系,解决了显示对象的定位的问题的。但以象素单位所建立的坐标系不符合用户(或程式员)的习惯,而且在不同分辨率的输出设备上,一个象素的大小也不相同的,这样,应用程式的输出在不同机器上会得到不同的结果。为解决这个问题,Windows引入了逻辑坐标系。他使得用户能够按照自己习惯使用的尺寸(毫米、英寸等)来描述客体,或绘制图像。用户在程式中使用逻辑坐标系中的坐标值,而由Windows根据映射方式将逻辑坐标系中的坐标值转算成设备坐标系中的坐标值(对于显示设备而言,具体映射到三个坐标系中哪一个取决于GDI函数中所使用的设备对象句柄)。映射方式也同时决定着逻辑坐标值的单位(简称逻辑单位)和坐标轴的正方向。在前面介绍的TextOut和DrawText()使用的是逻辑单位,而函数CreateWindow()使用的是屏幕坐标系中的坐标(设备单位,及象素)。程式员应该清楚什么时候在使用逻辑单位。一般而言,当映射方式起作用时,使用的是逻辑单位,而映射方式起作用的唯一时候是使用了那些需要将设备对象句柄作为参数的GDI函数的时候,但并非总是这样,因此,读者应注意这方面的问题。
表3-2给出的两个函数用于进行用户区坐标和屏幕坐标(注意是设备单位)之间的转换。
表3-2-1 ClientToScreen 函数





