GDI 映像方式 之 SetViewportExtEx 与 SetWindowExtEx 解析

所谓视口代表设备,比如屏幕。
窗口代表我们的思维。

我们对windows说在(5,6)处画个点(调用GDI函数)。windows认为是在我们的思维的(5,6)处画了个点。(也就是说5,6是逻辑坐标,GDI函数中的大部分都是逻辑坐标)

那么,要把它映射到屏幕上,必须作一些解释。

解释包括:
原点在哪里?

5,6代表什么?

注意,解释5,6时不光是距离问题,还有方向呢!

SetViewportOrgEx和SetWindowOrgEx是管第一个问题的。设置原点和设置X轴Y轴方向(SetMapMode)。

<< GDI 映像方式 之 SetViewportOrgEx 与 SetWindowOrgEx 解析>>

===================================================================================

SetViewportOrgEx 与 SetWindowOrgEx 解析

     这两个函数,用来改变视端口和窗口的原点,并都具有改变轴的效果,以致(0,0)不再指左上角。

   「视端口」是依据设备坐标(图素)的。通常,视端口和显示区域相同.视端口也可以是指整窗口坐标或者屏幕坐标。点(0,0)是显示区域(或者整个窗口或屏幕)的左上角,x的值向右增加,y的值向下增加。

   「窗口」是依据逻辑坐标的,逻辑坐标可以是图素、毫米、英寸或者您想要的任何其它单位。

对于视端口和窗口的概念可以这样理解:
幻想显示器大小可以随便改变,那么显示器每次都变成view「视端口」的太小就可以了,window「窗口」就没存在的必要了。

view「视端口」就是实际所需的大小;
window「窗口」就是显示器给你的限制。

再来看下Windows中的几种坐标体系

1、屏幕坐标  
屏幕坐标描述物理设备(显示器、打印机等)的一种坐标体系,坐标原点在屏幕的左上角,X轴向右为正,Y轴向下为正。度量单位是图素。原点、坐标轴方向、度量单位都是不能够改变的。
 
2、设备坐标(又称物理坐标)  
设备坐标是描述在屏幕和打印机显示或打印的窗体的一种坐标体系。坐标原点是在其客户区的左上角。X轴向右为正,Y轴向下为正。度量单位为图素。原点和坐标轴方向可以改变,但是度量单位不可以改变。
 
3、逻辑坐标  
逻辑坐标是在程序中控制显示,打印使用的坐标体系。该坐标系与定义的映射模式密切相关。默认的映射模式是MM_TEXT。我们可以通过设置不同的映射模式来改变该坐标体系的默认行为。
 
我们使用逻辑坐标系绘图,然后要在设备坐标系下显示。所以就有一个逻辑坐标和设备坐标之间的转换。


SetViewportOrgEx的参数总是使用设备坐标系单位(图素)。
假设显示区域为cxClient个图素宽和cyClient个图素高。映像方式为MM_TEXT。
如果想将逻辑点(0,0)定义为显示区域的中心,可进行如下呼叫:

SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; 
逻辑点(0,0)将映像为设备点(cxClient/2,cyClient/2)。

显示区域的坐标系变成如下形状:

xy1

 

SetWindowOrgEx的参数总是使用逻辑单位。
要想获得与上面使用SetViewportOrgEx同样的效果则可以进行如下呼叫:

SetWindowOrgEx (hdc, -cxClient / 2, -cyClient / 2, NULL) ;
逻辑点(-cxClient  / 2,-cyClient / 2)映像为设备点(0,0),即显示区域的左上角。

 

--------------------------------------------------------------------------------


很多人对于SetWindowOrgEx使用负数坐标参数表示很困惑,当然也包括我自己。进过几天的思考,终于恍然大悟。这里做一下解释。

首先要知道 不管对窗口和视端口原点作什么改变,设备坐标点(0,0)始终是显示区域的左上角。

我是这样理解的,窗口(逻辑)原点始终指向视端口(设备)原点。这样就很好解释了。

SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; 
逻辑点(0,0)将映像为设备点(cxClient/2,cyClient/2)。

设置视端口中心点为设备原点,逻辑原点映射之。

SetWindowOrgEx (hdc, -cxClient / 2, -cyClient / 2, NULL) ;
逻辑点(-cxClient  / 2,-cyClient / 2)映像为设备点(0,0),即显示区域的左上角。

将逻辑原点起始坐标设置为 (-cxClient  / 2,-cyClient / 2),再映射到设备原点。

假设函数调用时坐标如图所示:

   xy2

  

 

首先,将坐标(-50 , -50)设置为逻辑原点的起始坐标。

然后,将逻辑原点映射到设备原点,这里是显示区域的左上角。

函数调用后上图改变为:

xy3

当我们使用逻辑坐标-50,-50的时候,被映像到了设备原点,也就是显示区域的左上角。

当我们使用逻辑坐标0,0的时候,便被映像到了设备中心点。

我们绘图的时候使用的是逻辑坐标,系统显示图像的时候是使用设备坐标,所以会有一个转换过程。

现在我们在逻辑坐标50,50处进行绘图,映像方式为MM_TEXT(转换比率1:1),系统显示时转换为设备坐标:

设备坐标点X = (50 - (-50 ) ) * (1/1) + 0 = 100

设备坐标点Y = (50 - (-50 ) ) * (1/1) + 0 = 100

这下清楚了吧。

 

--------------------------------------------------------------------------------


再附下设备坐标与逻辑坐标的转换公式:

设备坐标点X = (待转换的逻辑点X - 逻辑坐标的窗口原点X) * (设备坐标的视端口范围X / 逻辑坐标的窗口范围X) + 设备坐标的视端口原点X

逻辑坐标点X = (待转换的设备点x - 设备坐标的视端口原点x) * (逻辑坐标的窗口范围x / 设备坐标的视端口范围x) + 逻辑坐标的窗口原点x

=======================================================================================

 

SetViewportExtEx和SetWindowExtEx是管第二个问题的。 设置比率。

其实想象一下也可以知道,5和6应该是乘上一个比率来变成像素单位。而后根据原点并按照X轴Y轴方向去画就可以了。
SetViewportExtEx和SetWindowExtEx就是决定比率的函数。(他们的第二个和第三个参数分别相除来代表横纵坐标的比率。)


SetWindowExtEx用于设置逻辑坐标范围。

SetViewportExtEx用于设置设备坐标范围。

必须在呼叫SetViewportExtEx之前呼叫SetWindowExtEx,以便最有效地使用显示区域中的空间。

举个例子:

SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,1,1,NULL);
SetViewportExtEx(hdc,cxChar,cyChar,NULL);
TextOut(hdc,3,2,TEXT( "Hello "),5);

 


由于TextOut的坐标值是3和2,在Windows98允许的范围32767之内,所以还是可以显示出 "Hello "字符串。
又因为程序把窗口的范围(逻辑坐标范围)定义为1,而视口的范围(设备坐标范围)定义为cxChar和cyChar(字符的平均宽度和平均高度),因此在显示时,Windows会在(3*(cxChar/1),2*(cyChar/1))的地方(也就是第二行的第三个字符处)显示字符串 "Hello "。

 

windows使用设备坐标进行显示,逻辑被转换为设备坐标:


 设备坐标点X = (待转换的逻辑点X - 逻辑坐标的窗口原点X) * (设备坐标的视端口范围X / 逻辑坐标的窗口范围X) + 设备坐标的视端口原点X

我们通过改一改数值来证明一下:
SetMapMode(hdc,MM_ANISOTROPIC);
SetWindowExtEx(hdc,4,4,NULL);     //设窗口范围(逻辑坐标范围)为4个逻辑单位
SetViewportExtEx(hdc,8,8,NULL);    //设视口范围(设备坐标范围)为8个物理单位(也就是8个像素)
TextOut(hdc,1,1,TEXT( "Hello "),5);  //在逻辑坐标(1,1)处显示 "Hello "


从上面的代码我们得出X轴的逻辑与物理比值为2,Y轴的逻辑与物理比值也为2,1*(8/4)=2,因此,Windows事实上会在客户区的左上角往右2个像素、往下2个像素的地方显示 "Hello "。


我们仍然可以把TextOut中的值进行修改:
TextOut(hdc,10,10,TEXT( "Hello "),5);


10明显超出了我们定义的逻辑范围4,但是因为它并没有超过坐标值的上限32767,因此,10*(8/4)=20,Windows仍然会在客户区的左上角往右20个像素、往下20个像素的地方显示 "Hello "。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值