Windows中的映射模式

 
 
一、Windows中的映射模式
1 、Windows定义映射模式的目的
经过我的综合,Windows定义映射模的目的又以下几个方面:1、不同人的使用习惯。不同国家的,不同地区,以及不同的人因为习惯喜欢用不同的度量单位,有的人人喜欢用英寸,而有的人喜欢用公制中的厘米,毫米等。其他的人又喜欢用另外一些单位。、2、使软件与硬件向分离开来。让开发的软件能够最大限度的与硬件无关。3、提供逻辑和物理的一种转换。就相当于银行的利率。
2 、默认的映射模式
默认的映射模式使MM_TEXT,它使以象素为单位的。X轴向左为正,Y轴向下为正。默认的坐标原点在左上角。
3 、固定比例映射模式
固定比例的映射模式有MM_LOMETRIC、MM_HIMETRIC、MM_LOENGLISH、MM_HIENGLISH、MM_TWIPS种。它们默认的坐标原点都使在左上角。其区别在于每一个逻辑单位对应的物理大小不一样。所对用的逻辑单位分别为0.1毫米,0.01毫米,0.01英寸,0.001英寸,1/1440英寸(0.0007英寸)。
4 、可变比例映射模式
对于可变比例的映射模式用户可以自己定义一个逻辑单位代表的大小,其大小可以任意。也可以让这个大小随环境改变而改变。有MM_ISOTROPIC,MM_ANISOTROPIC这两种映射模式。其逻辑单位的大小等于视口范围和窗口范围的比值。两者的不同在于前者要求X轴和Y轴的度量单位必须相同,而后者没有这样的限制。
二、Windows中的几种坐标体系
1 、屏幕坐标
屏幕坐标描述物理设备(显示器、打印机等)的一种坐标体系,坐标原点在屏幕的左上角,X轴向右为正,Y轴向下为正。度量单位是象素。原点、坐标轴方向、度量单位都是不能够改变的。
2 、设备坐标(又称物理坐标)
设备坐标是描述在屏幕和打印机显示或打印的窗体的一种坐标体系。默认的坐标原点是在其客户区的左上角。X轴向右为正,Y轴向下为正。度量单位为象素。原点和坐标轴方向可以改变,但是度量单位不可以改变。
3 、逻辑坐标
逻辑坐标是在程序中控制显示,打印使用的坐标体系。该坐标系与定义的映射模式密切相关。默认的映射模式是MM_TEXT。我们可以通过设置不同的映射模式来改变该坐标体系的默认行为。
三、逻辑坐标和设备坐标之间的转换
现有如下代码:
void CMapModeView::OnPaint()
{
CPaintDC dc(this);
 
// 获取设备类的设置
CPoint ptOrgView,ptOrgWindow;
CSize sizeView,sizeWindow;
CString strMsg;
 
ptOrgView=dc.GetViewportOrg();// 获取视口原点
ptOrgWindow=dc.GetWindowOrg();// 获取窗口原点
sizeView=dc.GetViewportExt();// 获取视口范围
sizeWindow=dc.GetWindowExt();// 获取窗口范围
 
strMsg.Format(_T("Viewport Extent:(%d,%d),/tViewport Org:(%d,%d)/tWindow Extent:(%d,%d)/tWindow Org(%d,%d)"),
sizeView.cx,sizeView.cy,ptOrgView.x,ptOrgView.y,
sizeWindow.cx,sizeWindow.cy,ptOrgWindow.x,ptOrgWindow.y);
TRACE("%s/n",strMsg);
 
// 设置映射模式以及原点
dc.SetMapMode(MM_TEXT);// 设置映射模式
dc.SetWindowOrg(100,100);// 设置窗口的坐标原点
dc.SetViewportOrg(200,200);// 设置视口的坐标原点
 
dc.SetWindowExt(5,10);// 改语句仅对可变比例映射模式有效
dc.SetViewportExt(1,1);// 同上
 
ptOrgView=dc.GetViewportOrg();
ptOrgWindow=dc.GetWindowOrg();
sizeView=dc.GetViewportExt();
sizeWindow=dc.GetWindowExt();
strMsg.Format(_T("Viewport Extent:(%d,%d),/tViewport Org:(%d,%d)/tWindow Extent:(%d,%d)/tWindow Org(%d,%d)"),
sizeView.cx,sizeView.cy,ptOrgView.x,ptOrgView.y,
sizeWindow.cx,sizeWindow.cy,ptOrgWindow.x,ptOrgWindow.y);
TRACE("%s/n",strMsg);
 
// 将点(300,400)从逻辑坐标体系映射到设备坐标体系。
CPoint ptMap;
ptMap=CPoint(300,400);
dc.LPtoDP(&ptMap);
strMsg.Format(_T("The Orginal Point(In LP):CPoint(300,400),Convert to DP is:CPoint(%d,%d)"),
ptMap.x,ptMap.y);
TRACE("%s/n",strMsg);
 
// 将点(300,400)从设备坐标体系映射到逻辑坐标体系
ptMap=CPoint(300,400);
dc.DPtoLP(&ptMap);
strMsg.Format(_T("The Orginal Point(In DP):CPoint(300,400),Convert to LP is:CPoint(%d,%d)"),
ptMap.x,ptMap.y);
TRACE("%s/n",strMsg);
}
以上代码最后调试输出结果为:
Viewport Extent:(1,1), Viewport Org:(0,0) Window Extent:(1,1) Window Org(0,0)
Viewport Extent:(1,1), Viewport Org:(200,200) Window Extent:(1,1) Window Org(100,100)
The Orginal Point(In LP):CPoint(300,400),Convert to DP is:CPoint(400,500)
The Orginal Point(In DP):CPoint(300,400),Convert to LP is:CPoint(200,300)
按照MSDN上,函数SetWindowOrg(x,y)设定设备坐标下的点(x,y)对应于逻辑坐标的原点。SetVieportOrg(x,y)设定逻辑坐标下点(x,y)对应逻辑坐标的原点。而实际上如果同时设置了逻辑坐标和设备坐标原点的话,那么以上的说法是错误的。
在默认映射模式MM_TEXT下,一个逻辑单位对应于设备坐标下的一个象素。改变默认原点以后的坐标体系如下图所示:
(0,0)              Dx,Lx       (0,0)                            
(100,100)                      Lx
(200,200)                  Dx
 .(300,400)
 
 
 
Dy,Ly                                Ly Dy
在VC中坐标系的转换和数学中的数学转化是不一样的。在这里是以距离为标准。首先看一下如何把点(300,400)如何从设备坐标转换成逻辑坐标。
在设备坐标体系下,点(300,400)与Y轴的距离为100个逻辑单位。那么所对应的逻辑坐标也要满足与逻辑坐标Y轴的距离为100个单位。又1个逻辑单位对应1个象素。所以所对应的设备坐标的X值为100+100=200。同样可以出对应的逻辑坐标的Y值为300。
按照同样的方法,我们也可以把逻辑坐标下的点(300,400)转换成设备坐标。在逻辑坐标下,点(300,400)与逻辑坐标Y轴的距离为200。那么在设备坐标体系,相应的设备坐标与设备坐标Y轴的距离也要为200。又1个逻辑单位对应1个象素,所以对应的设备坐标X值为200+200=400。同样的道理,可以求出对应的设备坐标Y值为500。
在这里,因为逻辑单位和设备单位一一对应,也可以把这个问题看作一个很简单的坐标平移问题来看。其结果是很显然的。
 
  2. 设备坐标
  Windows 将GDI函数中指定的逻辑坐标映射为设备坐标,在所有的设备坐标系统中,单位以像素点为准,水平值从左到右增大,垂直值从上到下增大。
  Windows 中包括以下3种设备坐标,以满足各种不同需要:
  (1) 客户区域坐标,包括应用程序的客户区域,客户区域的左上角为(0,0)。
  (2) 屏幕坐标,包括整个屏幕,屏幕的左上角为(0,0)。屏幕坐标用在WM_MOVE消息中(对于非子窗口)以及下面的Windows函数中:CreateWindow和MoveWindow(都对于非子窗口)、GetMessage、GetCursorPos、GetWindowRect、WindowFromPoint和SetBrushOrg中。用函数ClientToScreen和ScreenToClient可以将客户区域坐标转换成屏幕区域坐标,或反之。
  3. 逻辑坐标与设备坐标的转换方式
   映射方式定义了Windows如何将GDI函数中指定的逻辑坐标映射为设备坐标。要继续讨论映射方式我们要介绍Windows有关映射模式的一些术语:我们将逻辑坐标所在的坐标系称为"窗口",将设备坐标所在的坐标系称为"视口"。
  " 窗口"依赖于逻辑坐标,可以是像素点、毫米或程序员想要的其他尺度。
   对于所有映射模式,Windows都用下面两个公式将窗口坐标转换成视口坐标:
  xViewport=(xWindow-xWinOrg)*(xViewExt/xWinExt)+xViewOrg
  yViewport=(yWindow-yWinOrg)*(yViewExt/yWinExt)+yViewOrg
   其中,(xWindow,yWindows)是待转换的逻辑点,(xViewport,yViewport)是转换后的设备点。如果设备坐标是客户区域坐标或全窗口坐标,则Windows在画一个对象前,还必须将这些坐标转换成屏幕坐标。
   这两个公式使用了分别指定窗口和视口原点的点:(xWinOrg,yWinOrg)是逻辑坐标的窗口原点;(xViewOrg,yViewOrg)是设备坐标的视口原点。在缺省的设备环境中,这两个点均设置为(0,0),但它们可以改变。此公式意味着,逻辑点(xWinOrg,yWinOrg)总被映射为设备点(xViewOrg,yViewOrg)。
  Windows 还能将视口(设备)坐标转换为窗口(逻辑)坐标:
  xWindow=(xViewport-xViewOrg)*(xWinExt/xViewExt)+xWinOrg
  yWindow=(yViewport-yViewOrg)*(yWinExt/yViewExt)+yWinOrg
   可以使用Windows提供的两个函数DPtoLP和LPtoDP在设备坐标及逻辑坐标之间互相转换。
  4. 映射模式的种类
  Windows 定义了表1所列出的8种映射方式。
   上述映射模式中又可分成以下3类:
映 射 方 式
逻 辑 单 位
X 轴 增 加
Y 轴 增 加
毫 米
MM_TEXT
像 素 点
与 设 备 有 关
MM_LOMETRIC
0. 1mm
0.1
MM_HIMETRIC
0. 01mm
0.01
MM_LOENGLISH
0. 254mm
0.254
MM_HIENGLISH
0. 0254mm
0.0254
MM_TWIPS
0.0176mm
0.0176
MM_ISOTROPIC
任 意(x=y)
可 选
可 选
可 设
MM_ANISOTROPIC
任 意(x!=y)
可 选
可 选
可 设

  MM_TEXT
映射模式这种映射模式被称为"文本"映射方式,不是因为它对 于文本最合适,而是轴的方向与读文本的方向一致。Windows提供了函数SetViewportOrg和SetWindowOrg 用来设置视口和窗口的原点。缺省的窗口原点和视口原点均为(0,0),可以改变;缺省的窗 口范围和视口范围均为(1,1),不可改变。
   度量映射方式MM_LOMETRIC、MM_HIMETRIC、MM_LOENGLISH、MM_HIENGLISH和MM_TWIPS将1个逻辑单位映射为固定的实际单位,其中1twip等于0.0176mm(1/1440英寸)。其他映射模式对应的物理单位参见表1。设置了映射模式以后,Windows自动设置了窗口及视口的范围,范围本身的值并不重要,但范围比是一个固定的值,对于MM_LOMETRIC,Windows计算范围比xViewExt/xWinExt=0.1mm中水平像素的点数。
  SetMapMode(hDC,MM_ISOTROPIC);
  SetWindowExt(64,64);
  SetViewportExt(hdc,GetDeviceCaps(hdc,LOGPIXELSX),GetDeviceCaps(hdc,LOGPIXELSY));
   使用GetDeviceCaps函数可得到当前设备的各种能力,其第一个参数nIndex指示要获取信息的类型。当nIndex为HORZSIZE和VERTSIZE时,可得到显示区域的宽度和高度;当nIndex为HORZRES和VERTRES时,可得到每个水平和垂直方向的像素数即分辨率;当nIndex的值为LOGPIXELSX和LOGPIXELSY时,可得到水平和垂直方向每逻辑英寸所含像素数。
   以下是设置映射模式的代码
intxLogPixPerInch=GetDeviceCaps(hdc,LOGPIXELSX);
intyLogPixPerInch=GetDeviceCaps(hdc,LOGPIXELSY);
SetMapMode(MM_ANISOTROPIC);
SetWindowExt(100,100);
SetViewportExt(xLogPixPerInch,yLogPixPerInch);
   例如,要设置逻辑MM_TWIPS,函数SetWindowExt中的参数为应1440。
  2. 逻辑坐标与设备坐标转换时误差的处理
表2
映 射 模 式
每 英 寸 所 对 应 的 逻 辑 单 位 数
MM_LOENGLISH
100
MM_HIENGLISH
1000
MM_LOMETRIC
254
MM_HIMETRIC
2540
MM_TWIPS
1440
   可以采取以下两个步骤避免转换误差。(1)尽量选择窗口范围和视口范围比可以整除的映射方式,例如基于逻辑英寸的MM_TWIPS其窗口范围和视口范围比1440/96,可简化为15/1,从设备坐标转化为逻辑坐标时没有误差,从消除误差角度看,MM_TWIPS比其他几个映射模式都要好。(2)窗口范围和视口范围比不能整除时,也尽量将其简化,例如,当采用0.3900mm中的将1个逻辑单位映射成1/64英寸的映射方式时,其窗口范围和视口范围比值为64/96,可简化为2/3。如果我们将逻辑单位的值都取为2的倍数,设备单位的值都取为3的倍数,转换后就没有精度的丢失了。
   综上所述,如果我们能够根据映射模式值的特点,逻辑坐标和设备坐标都取经简化的窗口和视口范围值的倍数,则逻辑坐标和设备坐标间的转化将没有误差。
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值