GDI映射模式—关于窗口和视口

 

最近在学Windows编程,在学到GDI的时候给映射模式,尤其是窗口和视口之间怎么转换给搞得头大,现在总结一下,希望能给其他人一些帮助。

关于什么是设备坐标,什么是逻辑坐标,还有什么是设备坐标系统很多书上都有,这里就不再赘述,重点只讲一下窗口和视口是怎么转换的。首先讲一下三条规则,这是关键中的关键,一切的变化都由此而来。

(1) 映射模式被定义为从“窗口”(逻辑坐标)到“视口”(设备坐标)的映射。

(2) xViewport=(xWindow-xWinOrg)*xViewExt/xWinExt+xViewOrg

yViewport=(yWindow-yWinOrg)*yViewExt/yWinExt +yViewOrg

(3) 视口的(0,0)指的是客户区的左上角(也可以是屏幕或全窗口),x值向右增加,y值向下增加,这是不会改变的。

我们通过几个例子来解释。

一、 首先我们使用MM_LOMETRIC映射模式,它的x值向右增加,y值向下减小,视口范围是(1024-768),意思是指xViewExt=1024,yViewExt=-768,窗口范围是(3200,2400),意思是xWinExt=3200,yWinExt=2400。这里的范围请只把它理解成一个数,而不要理解成一个区间,因为它只是要用来求xViewExt/xWinExt这样一个比值而已。

一开始的时候,xWinOrg,yWinOrg,xViewOrg,yViewOrg的值都是0

所以当我们调用函数SetPixel(hdc,100,-100,0)时(GDI函数使用的参数是逻辑坐标,通过转换为(xViewportyViewport)找到在客户区的位置)

xViewport=(100-0)*(1024/3200)+0=32

yViewport=(-100-0)*(-768/2400) +0=32

也就是在客户区左上角右数32个像素点,下数32个像素点的位置画点。

而如果调用函数SetPixel(hdc,100,100,0),

yViewport=(100-0)*(-768/2400) +0=-32,对应的点在客户区上方,显示不出来。

因为MM_LOMETRIC模式不能修改范围,只能修改xViewOrgyViewOrg,所以我们可以使用函数SetViewportOrgEx(hdc,0,64,NULL)修改yViewOrg,这样就有

yViewport=(100-0)*(-768/2400) +64=32,即又显示在客户区左上角右数32个像素点,下数32个像素点的位置,直观上看是把坐标系的原点位置往下移动了64个像素点,可以这样想象一下,然而实质上的原因是yViewOrg的改变导致计算结果不同,设备点(0,0)仍然在客户区左上角,这一点一定要理解清楚。

 

二、上面的例子比较简单,为了加深理解,现在我们使用MM_ISOTROPIC模式,这个模式一开始的窗口范围和视口范围和MM_LOMETRIC相同,不同的是在这个模式下我们可以自己改变窗口范围和视口范围,且是各向同性的,也就是水平方向和竖直方向的每一个单位对应的像素点个数相同,。

和上面同样的问题在这个模式下我们有另外一种解决的方法,使用函数SetViewportExtEx(hdc,1024,768,NULL)改变yViewExt,则调用SetPixel(hdc,100,100,0)

yViewport=(100-0)*(768/2400) +0=32,这样又可以正常显示了。

这里要注意一点,改变了yViewExt之后,现在向下的方向成了y值增加的方向,因为yViewExt/yWinExt的值为正,所以点(0,100)和点(0,200)算出来后点(0,200)在点(0,100)下方,而原来向下的方向是y值减小的方向,因为yViewExt/yWinExt的值为负,点(0,-100)和点(0,-200)算出来后点(0,-200)在点(0,-100)的下方,这就是为什么说MM_ISOTROPIC模式x,y值增加的方向可选的原因。

MM_ISOTROPIC模式比较灵活,理解了它之后对于GDI映射就能比较好的理解,最后以构建笛卡尔坐标系为例来分析帮助理解。

(1)SetMapMode(hdc,MM_ISOTROPIC);

(2)SetWindowExtEx(hdc,1000,1000,NULL);

(3)SetViewportExtEx(hdc,cxClient/2,-cyClient/2,NULL);

(4)SetViewportOrg(hdc,cxClient/2,cyCleient/2,NULL);

(2)将窗口大小设定为1000,(3)把视口范围宽度设定为客户区宽度的一半,高度设定为客户区高度的一半的负数,此时xViewExt/xWinExt为正数,yViewExt/yWinExt为负数,整个客户区只可以显示x值为正数,y值为负数的点,相当于坐标系的第四象限。因为要保持各项同性,所以窗口大小1000就对应于客户区高度的一半(因为高度比宽度小)。(4)把xViewOrg设为cxClient/2,把xViewOrg设为cyClient/2,相当于把坐标系的原点移动到客户区中心。这样最终就创建了一个以客户区中心为原点的笛卡尔坐标系,并向各方向延展1000个单位。

到这里应该就差不多了,有不理解的请仔细琢磨一开始讲的那三条规则,以上是个人理解,希望能有帮助,如有错误请指出。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值