/////////////////////////////////////////////////
1.2.2 映射模式样
vc++中采用的坐标映射方式使得用户图形坐标和输出设备的像素完全一致,当屏幕的像素大
小为800*600时,每逻辑英寸包含的屏幕像素数为96,而打印机则需要多出
好几倍的点数才能到达同样的逻辑尺寸。例如:HP打印机每逻辑英寸包含的打印机点数为600,
也就是说打印机的清晰度比屏幕要高很多。这样的后果就是在屏幕上显示出来的满屏幕的图像
在打印出来的纸上却只有一点点,怎么解决这个问题呢?一种简单的方法就是转换坐标映射方式,
使得打印时采用的坐标比例比显示时采用的坐标比例相应地大若干倍.
映射模式的意思是在屏幕或者打印机上绘图的时候,可以使用英寸或者毫米作为单位,这样更加直观.
这其中要注意设备单位和逻辑单位的区别:逻辑单位是传递给绘图函数的x和y值,它们可以表示英寸和
毫米,而设备单位是x和y在屏幕上的像素数,或是打印机上的点阵数。单击鼠标以设备单位返回。如果
想知道鼠标单击位图的什么位置,需要将设备单位转化为逻辑单位。表1-5所示是可用的映射模式。
映射模式 逻辑单位
MM_TEXT 一个像素
MM_LOMETRIC 0.1毫米
MM_HIMETRIC 0.01毫米
MM_LOENGLISH 0.01英寸
MM_HIENGLISH 0.001英寸
MM_TWIPS 1/1440英寸
MM_ISOTROPIC 用户定义的值,但是x和y方向相等
MM_ANISOTROPIC 用户定义的值,但是x和yy方向任意
映射模式通过设备环境类的一个成员函数SetMapMode()来设置.只要把上述标志当作参数
传入函数即可.设置映射模式后,传给任何绘图函数的坐标值都通过GDI内部的映射机制转
换成设备坐标.如果把映射模式设置为MM_LOENGLISH,然后向绘图函数传递一个100的逻辑
单位值,映射模式知道用户实际想要的是100*0.1mm,也就是1cm。
映射模式MM_ISOTROPIC和MM_ANISOTROPIC允许改变比例因子和原点,使用这些模式改变窗
口大小时,绘制的内容也会改变大小。
使用MM_ISOTROPIC方式,x和y始终保持1:1的比例。如果在屏幕上画了一个圆,无论比例因
子如何改变,始终还是圆,而在MM_ANISOTROPIC方式中,x和y比例因子可分别改变,圆会被
压成椭圆。
有一点需要注意:当使用MM_TEXT映射模式时候,y轴的正方向是沿屏幕垂直向下的,x轴是沿屏幕
向右的.然而,其他的映射模式的y轴正方向是沿屏幕向上的,x轴正方向也是向右的.这一点特别容易
搞混了.
我们定义两个矩形,设置从逻辑环境到设备环境的转换。第一个矩形以逻辑单位表示绘制区域的大小,
windows术语称之为窗口,第二个矩形以设备单位(即像素)表示第一个矩形大小代表的设备范围大小,
在Windows术语中称之为视口,两种关系如图:
1、设置视口到视图的客户区,并可忘记它。SetViewportOrg(0,0);SetViewPortExt(100,50);
2、把窗口的初始位置设置在想在逻辑环境中看到的地方:SetWindowOrg(100,100);
3、要缩小图形,只要缩小窗口的范围。要放大图形,只要增大窗口范围。要滚动图形,只要改变
窗口的初始位置。
SetWindowOrg()用来改变窗口坐标(逻辑坐标)的原点,SetViewPortOrg()用来改变视口坐标(设备坐标)
的原点。
void CPrintProjView::OnDraw(CDC *pDC)
{
pDC->SetMapMode(MM_TEXT);
pDC->SetViewPortOrg(50,50);
pDC->SetWindowPortOrg(200,200);
CPen myPen(PS_SOLD,1,RGB(0,255,0));
Cpen *pOldPen = pDC->SelectObject(&myPen);
pDC->TextOut(200,200,_T("窗口映射模式"));
pDC->Rectangle(200,200,400,400);
pDC->SelectObject(pOldPen);
myPen.DeleteObject();
}
这段代码,把视口原点设置为设置坐标(50,50),把窗口原点设置为逻辑坐标(200,200),
然后通过窗口原点(200,200)绘制一个长宽各为200的方框.逻辑点(200,200)映射到设备
点(50,50),即把窗口原点映射到视口原点.
SetWindowExt()用来设定逻辑环境的大小,SetViewPortOrg()用来设定设备环境的大小.映射
模式MM_ISOTROPIC和MM_ANISOTROPIC允许调用SetWindowExt()和SetViewPortExt()函数来设置
设备坐标和逻辑坐标之间的比例.
可以用下面的公式实现逻辑单位到设备单位的转换:
x比例因子 = x视口长度/x窗口长度
y比例因子 = y视口长度/y窗口长度
设备x = 逻辑x * x比例因子 + x原点偏移量
设备y = 逻辑y * y比例因子 + y原点偏移量
设备环境本身提供了两个函数实现逻辑坐标和设备坐标之间的互换.DPtoLP()函数,可以
接受一个指向CPoint类或者CRect类对象的指针作为参数,然后把它所指向的对象从设备
坐标转换为逻辑坐标,LPtoDP的作用正好相反.
下面这段程序根据GetClientRect()函数返回窗口客户矩形,函数SetWindowExt和SetViewportExt
一起设置比例,结果窗口大小恰好是800*800,SetViewPortOrg函数把原点放置在窗口中心.这样椭
圆恰好充满整个屏幕.
void CPrintProjView::OnDraw(CDC *pDC)
{
CRect rcClient;
GetClientRect(&rcClient);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(800,800);
pDC->SetViewportExt(rcClient.right/2,rcClient.bottom/2);
CPen myPen(PS_SOLID,1,RGB(255,0,0));
CPen *pOldPen = pDC->SelectObject(&myPen);
pDC->Ellipse(-400,-400,400,400);
pDC->SelectObject(pOldPen);
myPen.DeleteObject();
}
注意:SetWindowExt()和SetViewPortExt()函数只有在MM_ANISOTROPIC和MM_ISOTROPIC模式下才有效,
在其他模式下,对它们的调用将被忽略。无论彩用哪种映射模式,GetClientRect()和GetWindowRect()
函数返回的都是设备坐标(即像素)。