http://hi.baidu.com/juery/blog/item/affcd76274545bc9e7113ad1.html
最近遇到“视口”与“窗口”的问题,想想以前在这个问题上也纠缠了过一段时间,现在看来是主要是很多书籍中将原点与(0,0)点的概念弄复杂了,在数学上,原点的定义应该就是(0,0),但是这些书籍中总让人感觉这两个点不是同一个点。比如在孙鑫老师的《VC++深入详解》中提到:
如果将视口原点设置为(xViewOrg,yViewOrg),则逻辑点(0,0)会被映射为设备点(xViewOrg,yViewOrg)。
如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)将会被映射为设备点(0,0),即设备客户区左上角。
后面又提到:不管对窗口和视口原点如何改变,设备点(0,0)始终是客户区的左上角。
查《Windows程序设计(第五版)》,里面的说法基本也差不多。虽然也是说视口对应设备坐标,窗口对应逻辑坐标,但视口是视口原点并不是对应了设备点(0,0),如果按书中所说的窗口和视口只是坐标单位不同,两者具有一一对应的关系,那么SetViewportOrg函数和SetWindowOrg函数按字面意思,两者设置的原点是的方式应该是一致的,只是偏移量的单位不同而已,但实际上二者要取得同样的效果,他们的参数的数值是相反的。
既然视口对应的是设备坐标,那么视口原点对应的就应该是设备点(0,0),而设备点(0,0)始终是客户区的左上角,那么只要客户区没变化,视口原点是不能改变的,看上面的话就感觉这视口原点和设备点(0,0)就不是同一个点了。个人觉得这实际上是同一个点,那么SetViewportOrg函数又有什么意义呢,个人觉得这是函数字面意义的误导,这个函数和SetWindowOrg函数都只是设置窗口和视口之间的映射关系,只是两者出发的角度不一样而已,上面的两句话也可以这么说:
SetViewportOrg(xViewOrg,yViewOrg)将设备(视口)坐标(xViewOrg,yViewOrg)映射为逻辑坐标(0,0)。
SetWindowOrg(xWinOrg,yWinOrg)将逻辑(窗口)坐标(xWinOrg,yWinOrg)映射为设备坐标(0,0)。
因为设备坐标(0,0)是不变的,因此整个设备坐标系相对于视口矩形区域是固定的,因此这两个函数通过改变映射关系来改变的都只是逻辑坐标的原点(窗口原点),而不是改变设备坐标原点(视口原点),前者将逻辑坐标的原点映射成设备坐标的(xViewOrg,yViewOrg),后者将逻辑坐标原点映射成设备坐标的(-xWinOrg,-yWinOrg)。因此,在默认MapMode下,SetViewportOrg(x,y)和SetWindowOrg(-x,-y)效果是一样的。
将个人理解总结起来如下:
1.窗口对应的是页面空间,就像整个网页一样,视口对应的是客户区的显示区域,当网页高度不超过窗口(此处窗口指通常意义上的桌面窗口)客户区显示高度时,窗口和视口的实际大小是一样的,只是坐标单位不同。当网页高度超过窗口客户区显示高度时,窗口指整个网页,而视口则只是指客户区显示的那一块。
2.视口为设备显示区域,所说的客户区不一定就是窗口(此处窗口指通常意义上的桌面窗口)客户区,根据不同的DC创建方式而定。
3.视口对应的是设备坐标,与设备有关;窗口对应的是逻辑坐标,与设备无关。使用GDI绘图室,将逻辑坐标转换为设备坐标,Window系统再将设备坐标转换为物理坐标(不是程序员需要干的事情)。
4.所谓的SetViewportOrg和SetWindowOrg并不是设置神马原点,而是改变映射关系,只是映射出发的角度不同。
不知我的理解是否正确,欢迎大家指正。
[又仔细研究,发现上述理解不对,新的理解如下]
1.窗口坐标和视口坐标是一一对应的关系,但是窗口和视口所在坐标系也不一样,前者处在逻辑坐标系,后者处在设备坐标系,但是窗口原点并不一定就是窗口坐标系的原点,同样,视口原点也不一定就是设备坐标系的原点,但是窗口坐标点与视口坐标点是对应的,因而这所处坐标系不同,所以在相应的坐标系中的坐标也不同。关系如下图:
2.设备坐标系的原点始终是客户区(根据DC确定)的左上角;
3.逻辑坐标和设备坐标之间的联系通过设置窗口坐标和视口坐标之间的映射来建立。
以下假设初始的窗口原点和视口原点在各自坐标系中的位置均为(0,0):
4.采用SetViewportOrg(x,y)可设置视口原点在设备坐标系中的位置(x,y),因视口原点与窗口原点映射,因此这一函数的作用即是将窗口原点映射为新的视口原点[即:设备坐标系中的(x,y)]。
SetViewportOrg(x,y)后的效果(其中x,y均为负值)
5.采用SetWindowOrg可设置窗口原点在逻辑坐标系中的位置(x,y),因窗口原点与视口原点映射,因此这一函数的作用即是将新的窗口原点[即:逻辑坐标系中的(x,y)]映射为视口原点。因为设备坐标系的原点始终是客户区的左上角,因此,该函数的作用实际是将逻辑坐标系相对于原来的位置偏移(-x,-y),因此,在默认MapMode下,SetViewportOrg(x,y)和SetWindowOrg(-x,-y)效果是一样的。
SetWindowOrg(x,y)时的效果(其中x,y均为正值)
6.图形最终按设备坐标显示。