zhangwei_life的大作:
一、理论准备
首先在深入vc学习坐标映射的相关知识前,我们必须要知道两个不同的平面直角坐标系应该如和进行转换。
逻辑坐标系:顾名思义,既然是逻辑的,也就是我们想象的。它是不受任何设备因素的限制的。这极其类似于平面几何中直角坐标系,原点我们可以任意定,x轴,y轴的相对方向和位置可以任意定,定义原点之后,我们可以以任意的长度进行绘图,平面空间无限大。可以这样说,逻辑坐标系没有单位可言,因为他是脱离物理设备的。
设备坐标系:由于各种原因,大多数是因为历史原因,我们的设备坐标系的原点、x轴、y轴方向是固定的。即物理设备的左上角点为原点(0,0),x轴水平向右增大,y轴垂直向下增大,单位是像素。记住,设备坐标系得坐标系的以上各种属性永远不会发生变化,至少在vc中。
窗口(window):可以这样理解,在vc中窗口就好比我们的绘图板,采用逻辑坐标系。
视口(viewport):顾名思义,是我们用来观察窗口的一个取景器,自然是物理设备,采用的是设备坐标系。
写到这里,问题就来了,我们如何使用视口来观察窗口呢,呵呵。这就是我们经常搞不清楚的。换句话说,如何使用设备坐标系来展示我们的逻辑坐标系。
让我们抛开vc的繁文缛节,暂时超脱红尘,返璞归真的想一下,如果是你你会怎么做呢?
logicalH
|
deviceH
|
|
|
deviceW
|
逻辑矩形
|
|
logicalW
|
|
设备矩形
|
因此逻辑长度/设备长度=logcialH/deviceH=logicalW/deviceW。这又带来了一个问题,logcialH/deviceH,logicalW/deviceW如果不相等怎么办呢?于是我们又有了两个方案。一个是在两个方向上使用不同的逻辑和设备比率,另一个是在两个方向上采用同样的逻辑和设备比率,具体采用哪一个都可以。到目前为止,我们已经解决了逻辑与设备的数值转换问题。
然而,可以想象假设一个逻辑的点叫做(50,60)那么他转换成设备的点时,坐标是多少呢?你当然想到了,我们应该让逻辑和设备坐标的原点(0,0)重合,因为逻辑和设备的点坐标都是相对于他们的原点而言的,非常好。但是我们为什么不能够更加灵活一点呢,我们设定一个逻辑点A,和一个设备点B,同时要求在进行转换时A,B两点必须重合,这样既使得逻辑和设备的转换有了参照系,又可以让两个坐标系之间进行相互的平移。哇,我们不知不觉已经完成了逻辑坐标到设备坐标的转换,呵呵。
然而,我们知道目前我们所说的设备坐标的单位是像素,那么像素又是什么呢?按照我们的理解,对于显示器、打印机等显示设备而言,像素就是它们可以输出的最小的一个点。天哪,问题又来了,看来像素也不是真实的、物理的度量单位,因为只要输出设备不同,我们就不敢保证他们所能够打印的最小的点的大小是相同的。以一英寸为例,在不同的输出设备上,组成他们的点的个数是不一样的,换句话说,一英寸长度所包含的像素的个数是不一样的。呵呵,我们当然不是上帝,也不是天才。前辈们自然已经解决了这个问题,他们定义了设备的输出分辨率,DPI,叫做dots per inch,中文叫做点每英寸。
是不是很有意思呢?呵呵,逻辑坐标,设备坐标,最后才是真实的、我们在日常生活中用到的英寸、厘米啦之类的公制单位。因此,对于如上的事实进行一个总结。
为了在显示输出设备上进行打印或显示,我们必须具备以下几个条件:
1.
逻辑坐标系的x,y轴的方向
2.
设备坐标系的x,y轴的方向(windows中已经固定,且设备左上角点为原点)
3.
映射的重合点
4.
比例矩形,用来设定在x,y方向上逻辑到设备尺寸的转换比率(L/D=k)
5.
显示设备的分辨率,定义了设备像素和真实的物理尺寸之间的比率关(m个设备像素构成一英寸)
现在我们来模拟计算一下长度为ll的逻辑长度换算成一英寸的过程
ll=ll/k 个像素=ll/k * (1/m) 英寸=ll/(k*m)英寸
我们也可以理解为
每一个逻辑单位等于
1/(k*m)
英寸
,
我们姑且称之为
”
逻辑单位的真实尺寸
”
二、Vc中的相关映射模式
为了方便广大用户使用,盖茨大哥已经为我们事先设定一些上述条件,并将它们称之为映射模式。总共有三大类。
l
MM_TEXT
l
MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS
l
MM_ISOTROPIC、MM_ANISOTROPIC
|
逻辑坐标
|
设备坐标
|
映射重合点
|
比例矩形
|
逻辑单位的真实尺寸
| ||||
|
x轴
|
y轴
|
x轴
|
y轴
|
逻辑点A
|
设备点B
|
逻辑矩形
|
设备矩形
|
|
MM_TEXT
|
→增大
|
↓增大
|
→
增大
|
↓
增大
|
默认为(0,0)
SetWindowOrg
可以修改
|
默认为(0,0)
SetViewportOrg
可以修改
|
系统提供,固定
|
系统提供,固定
|
1逻辑单位=1像素
|
MM_LOENGLISH
|
→
增大
|
↑
增大
|
1逻辑单位=0.01英寸
| ||||||
MM_HIENGLISH
|
1逻辑单位=0.001英寸
| ||||||||
MM_LOMETRIC
|
1逻辑单位=0.1毫米
| ||||||||
MM_HIMETRIC
|
1逻辑单位=0.01毫米
| ||||||||
MM_TWIPS
|
1逻辑单位=1/120个像素
| ||||||||
MM_ISOTROPIC
|
由SetWindowExt(lw,lh)和SetViewportExt(dw,dh)共同决定,当lw和dw的符号相同时,逻辑坐标X和设备坐标X同向→增大,否则反向←增大。lh和dh同理。
|
SetWindowExt(lw,lh)
|
SetViewportExt(dw,dh)
|
X,y两个方向的比率必须相同,如果lw/dw和lh/dh的比率不同则采用较小的那个。
| |||||
MM_ANISOTROPIC
|
X,y轴可以采用不同的比率,各自保持。
|
三、VC中几个重要的和坐标系相关的函数的说明
pDC->GetDeviceCaps:得到的数据都是设备坐标,单位是像素,最左上角为原点,x向右增大,y向下增大
pDC->SetViewportOrg、SetViewportExt使用的都是设备坐标系,单位都是像素。你可以把它们看作是你的取景器,要么是显示器上的窗口,要么是空白的打印纸。
pDC->SetWindowOrg、SetWindowExt使用的都是逻辑坐标系,
CPoint,CRect,CSize他们则是一些普通的类,用来承数据而已,可以放置逻辑或设备坐标,就像水桶一样,装水可以,装粥也可以。这完全取决于你。
GetClientRect 是CWnd的一个成员函数,目的是得到客户区域的大小,自然也是设备坐标系,得到的是像素。