窗口映射专题研究(第2版)一、2018年重新总结

在这篇文里,我希望能把概念缕清,特别写了一个长篇,需要慢慢的读,读完也许会解决映射的问题。

窗口映射涉及到三个坐标系,分别为窗口坐标,视口坐标和设备坐标。

为了清晰的表达这几个概念,需要对每一个概念进行单独的记录,也就是说不急着先讲什么映射,而是先把每一个概念缕清楚。第一个先说设备坐标。

设备坐标

设备坐标,先看设备这个词,顾名思义就是指物理设备,看的见摸的着,比如屏幕等。

设备坐标有两个特点:

1、向右为正,向下为正,原点处于客户区左上角。
2、恒定不变。也就是说,不管如何映射,转换等等任何操作,设备坐标永远不变,而且以像素为单位

这两条规则很重要,因为后面会用到。

上图所示为客户区的设备坐标,从图可以看出,向右为正,向下为正,那么向上肯定为负,向左也为负,虽然另外两条坐标轴没有标出来,但是不代表没有,这样就是一个完整的坐标系统。但是明显和我们常用的笛卡尔坐标不一样,因为我们习惯x轴向右为正,y轴向下为负。

现在以这个坐标轴为标准,回答一个简单的问题,(100,100),(100,-100)在哪里?

根据坐标轴规定的方向,我们可以得出位置如下:

逻辑坐标

为了最大限度的简化问题,现在采用最简化的方式来说逻辑坐标,所谓的逻辑坐标就是笛卡尔坐标系,我们先认定这个规则。

如图所示,向右为正,向上为正,这个终于和我们的习惯接壤了。同时,这个逻辑坐标是画图函数的坐标依据。

比如:

pDC->Lineto(100,100),请问这个(100,100)在哪里?

因为逻辑坐标是以笛卡尔坐标为准,所以我们可以知道位置如下:

现在我们已经知道两套坐标系统,一个是逻辑坐标,一个是设备坐标,假如再也没有其它什么坐标系统了,事情就简单了不是吗?因为逻辑坐标是什么值直接它把标到设备坐标上去不就行了吗。

比如:

pDC->moveTo(0,0);

pDC->LineTo(100,100)

这两句代码用的是逻辑坐标,因为前面说过,画图函数采用的是逻辑坐标
从字面上翻译就是DC先移到逻辑坐标(0,0),然后画线到逻辑坐标(100,100)。

现在,我们假定逻辑坐标的值在哪,就把它标到设备坐标上对应的位置,我们区别的唯一依据肯定就是正负方向,请看下图:

这样是没有问题的,逻辑坐标是(0,0),对应设备坐标的(0,0),逻辑坐标的(100,100)对应的设备坐标是右下角的(100,100),像上文所说,如果这样一切问题都没有了。但是在这个时候,又出现一个视口坐标。

视口坐标

视口坐标系统出现了,它处于逻辑坐标和设备坐标的中间。先给一个概念:

1、视口坐标是操作系统干的事
2、我们假设视口坐标系统是虚拟的。

下面详细来说

前文讲过,如果没有出现视口,一切都是没问题的,逻辑坐标在哪,就在设备坐标的相应位置标上即可。现在操作系统要求规则换一换,不要这样映射,而是给一种映射方式,原来是逻辑坐标转向于设备坐标,现在是逻辑坐标向视口坐标转换。

也即:

之前     逻辑坐标——>设备坐标(之前假设的)
之后     逻辑坐标——>视口坐标

不以设备坐标为准,而是以视口坐标为准,那么我们自然就提出两个关键的问题:

1、视口坐标系统的正负方向是如何朝向的?
2、视口坐标的原点在哪儿?

解释第一条:坐标系统的正负方向是很重要的,不言而喻。但是前面可以看出,已经出现两种方向了,说明坐标系统是乱的,各种各样的,所以我们有必要知道视口坐标系统的正负方向。
解释第二条:坐标系统的原点同样重要,这是画图的依据。

解决第一个问题:

操作系统:规定几种映射方式,每种映射方式都有规定坐标系统的正负方向,在默认情况下是MM_TEXT,也就是x向右为正,y向下为正,原点和设备坐标原点相同。

一看到这个方向,马上就想到,这不是和前面的设备坐标是一样的吗?确实是一样的,于是,得出下面的结论:

1、默认的视口坐标映射方式是MM_TEXT,向右为正,向下为正,和设备坐标相同(这里多写一句,是正好相同)
2、默认的视口坐标原点和设备坐标相同,位于客户区左上角。

现在我们的映射方式发生本质改变,逻辑坐标不再和设备坐标打交道,而是和视口坐标系统进行转换。

观察这个图,设备坐标是永恒不变的,依然处于客户区左上角,只是多出了一个视口坐标,这个视口坐标恰好与设备坐标重合。

再看原来的两句代码:

pDC->moveTo(0,0);
pDC->LineTo(100,100);

这两句是逻辑坐标,现在映射到视口坐标,如下:

一切都很好,也没有什么问题,这也是程序中真正的实现方式

现在出现一个问题,因为前面说过,视口坐标原点默认是和设备坐标相同的,既然是默认,那么就有更改的可能,现在假设想把视口坐标原点往右下角移一移,也是可以的,这样就出现一个函数
SetViewportOrg(100,100);

这个函数非常关键,下面详解的说下:

首先,SetViewportOrg里面的(100,100)单位是设备坐标,也就是像素,因为在讲设备坐标的时候已经明确说了,设备坐标的单位是像素。按照函数的名字可以知道,这个函数是设置视口原点在设备坐标的(100,100)处,也就是说移动视口坐标原点也得有个依据点,不然这个(100,100)是依据哪个参照物进行移动的呢?

显然,这个参照物就是设备坐标原点,也就是说把视口的原点移动到设备坐标的(100,100)处。

看下面这个图

如上图所示,(100,100)是相对于设备坐标来说的,但是经过移动之后就变成视口坐标的原点。

这里再强调一下,设备坐标的(100,100)是永远不变的(100,100),它可不管外面的坐标系统怎么变化,设备坐标系统的(100,100)的位置永远就在右下角的那个红色圆点处

但是视口坐标原点却是可以移动的。同样道理,一个相同的逻辑坐标(100,100),在视口各种移动之后映射的位置自然也就不同了。

现在该说说逻辑坐标了,逻辑坐标从来不管视口坐标怎么变,设备坐标在哪,它只和视口坐标进行位置交换,逻辑的(0,0)就是视口的(0,0),逻辑的(100,100)就是视口的(100,100),这样不是很清晰了吗?

逻辑坐标不认识设备坐标,只和视口坐标打交道。
而视口坐标却可以参照设备坐标进行坐标移动。

结束

原文地址:https://www.cnblogs.com/tinaluo/p/8259071.html