理解Windows坐标系
一.设备坐标和逻辑坐标
设备坐标(Device Coordinate)又称为物理坐标(Physical Coordinate),是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。
屏幕上有三种不同的物理坐标,每种物理坐标是固定死的,原点,XY轴方向都不变。
1、客户区域坐标,包括应用程序的客户区域,客户区域的左上角为(0, 0)。
2、屏幕坐标,包括整个屏幕,屏幕的左上角为(0, 0)。
用函数ClientToScreen和ScreenToClient可以将客户区域坐标转换成屏幕区域坐标,或反之。
3、全窗口坐标,包括一个程序的整个窗口,包括标题条、菜单、滚动条和窗口框,窗口的左上角为(0,0)。
逻辑坐标(Logical Coordinate)是系统用作记录的坐标,是以逻辑单位为单位来表示的。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。
逻辑坐标有多种映射模式,可以改变坐标方向和每个逻辑单位的大小。
画图在逻辑坐标中画,使用逻辑单位,显示图形在物理坐标中显示。
二.窗口和视口
视口:以像素(即设备坐标)为坐标单位,即用户在屏幕上所观察到的应用程序客户区的一块屏幕区域。
窗口:应用程序中的坐标范围,对应逻辑坐标,如1km×2km,在显示时,Windows需要将窗口坐标(即逻辑坐标)映射到视口坐标中(即设备坐标)。
这里说的窗口应该是概念上的世界窗口,比如你要显示的图象是2000*3000像素,则这个窗口就是2000*3000像素。而视口是定义在屏幕窗口上的一块区域,比如定义为200*300像素的屏幕窗口区域,且与世界窗口的映射是1:1,则视口不能完全显示世界窗口的内容,需要滚动。一般视口是定义为屏幕窗口显示区域的大小。
考察窗口和视口主要考察它们的原点坐标的设置(SetViewportOrg,SetWindowOrg)和坐标单位映射关系(SetViewportExt,SetWindowExt)。
三. SetViewportOrg和SetWindowOrg
1.SetWindowOrg 是把设备坐标的原点移动到逻辑坐标的(X, Y)处。
2.SetViewportOrg 是把逻辑坐标的原点移动到设备坐标的(X, Y)处。
参见Sample0.
四. SetWindowExt和SetViewportExt
SetWindowExe设定窗口尺寸,SetViewportExt设定视口尺寸,窗口尺寸以逻辑单位计算,视口尺寸以物理单位计算。
调用SetMapMode(MM_ANISOTROPIC)时,逻辑描画领域坐标系的原点与画面的左上角是重叠的。然后需要调用SetWindowExt()函数和SetViewportExt()函数,来设定纵轴横轴的単位和方向以及伸缩比例。
virtual CSize SetWindowExt(int cxWindow, int cyWindow);
virtual CSize SetViewportExt(int cxViewport, int cyViewport);
一般说SetWindowExt()函数和SetViewportExt()函数要成对调用。它们的意思(功能)是:用cxViewport个物理像素来表现cxWindow个逻辑点(数学上的长度)。同样用cyViewport个物理像素来表现cyWindow个逻辑点(数学上的长度)。cx和cy看起来好像是为了设定描画范围参数,其实不然。很简单,它们是代表逻辑长度与物理长度的比值的分子和分母。正负符号也可以设定。当cxViewport/cxWindow为正的情况下,X轴的方向是指向右方,反过来指向左方。 cyViewport/cyWindow为正的情况下,Y轴的方向是指向上方,反过来指向下方。
参见Sample1.
五. SetMapMode
该函数设置指定设备环境的映射方式,映射方式定义了将逻辑单位转换为设备单位的度量单位,并定义了设备的X、Y轴的方向。
Windows定义了8种映射方式,它们在WINGDI.H中相应的识别字和含义如表5-5所示。
映射方式 |
逻辑单位 |
x值(增加) |
y值(增加) |
MM_TEXT |
图素 |
右 |
下 |
MM_LOMETRIC |
0.1mm |
右 |
上 |
MM_HIMETRIC |
0.01mm |
右 |
上 |
MM_LOENGLISH |
0.01in |
右 |
上 |
MM_HIENGLISH |
0.001in |
右 |
上 |
MM_TWIPS |
1/1440in |
右 |
上 |
MM_ISOTROPIC |
任意(x=y) |
可选 |
可选 |
MM_ANISOTROPIC |
任意(x!=y) |
可选 |
可选 |
参见Sample2.
六.综合运用1(加入滚动条)
滚动条的作用:用来帮助尺寸有限的屏幕窗口显示区域察看无限大的逻辑空间中的内容。逻辑空间是无限大的,屏幕窗口是有限的,利用滚动条可以观察到更多逻辑空间中的内容。
SCROLLINFO si;
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
si.nMin = 0;
si.nMax = nHScrollMax;
si.nPos = m_nHScrollPos;
si.nPage = m_nHPageSize;
SetScrollInfo (SB_HORZ, &si, TRUE);
设置垂直方向上可以观察到的逻辑空间内容的范围。
滚动条位置坐标是设备坐标。
参见Sample3.
七.综合运用2(加入滚动条及图片缩放)
参见Sample4.
八.最后总结
① 可以认为CDC的所有成员函数都以逻辑坐标为参数。
② 可以认为CWnd的所有成员函数都以设备坐标为参数。
画图并移动图像的步骤:
1.在脑海中建立逻辑坐标,物理坐标。
2.确定逻辑坐标的映射模式(即确定轴方向和像素点大小)。
3.用CDC函数开始在逻辑坐标中画图。
4.使用视口或窗口原点来移动图像到想要的位置。(设置视口或窗口原点)。
问:当滚动条右向拉10个单位,逻辑坐标的(0,0)到什么地方去了呢?
答:还是(0,0)
分析:滚动条移动是视口移动了.变化的是视口的坐标原点,相当于SetViewportOrg(-10,0)函数的功能。