映射模式/视口(viewport)和窗口(window)

 

 OnPaint()
{
    根据窗口大小算出新的图形坐标;
    使用计算出的图形坐标绘制图形;
}
这样每次拖动后,OnPaint()就会被调用,自然就成比例了。

*****************************************************************************************************************************************

'视' (View) 是 '窗口' (Window)的一种。像你现在看到的浏览器,整个IE就是'窗口'(Screen/Window),而显示网页的区域就是'视口'(Client/View)。视口是显示文档的区域,即客户区!

窗口是依据逻辑坐标的,逻辑坐标可以是图素、毫米、英寸或者您想要的任何其它单位。您在GDI绘图函数中指定逻辑窗口坐标;视口是相对于设备坐标而言的。

MM_ISOTROPIC --> 长宽比例保持一致,相当于设备长宽比变了后,图形也不会变形
MM_ANISOTROPIC --> 长宽比例根据设备坐标的长宽自动调整,可以不成比例

 pDC->SetMapMode(MM_ISOTROPIC);
 pDC->SetWindowExt(XRange/Rect.width, YRange/Rect.Height); // XRange指x方向需要画的点数,Rect.width是画布宽度
 pDC->SetViewportExt(1,1); //设置1,意思是指在一个像素点上能画XRange/Rect.width个点

 pDC->SetViewportOrg((rc.right+rc.left)/2, (rc.bottom+rc.top)/2);  //将设备坐标点((rc.right+rc.left)/2, (rc.bottom+rc.top)/2)映射为逻辑坐标原点(0, 0) 
   
你定了窗口的大小,视口的大小,那么你在窗口上的画图操作映射的视口(也就是显示设备上)的比例也就确定了  :视口大小/窗口大小,即 XRange/Rect.width 和 YRange/Rect.Height。这样点的一个像素大小在显示设备上将按这个比例缩放(即一个像素点能画几个点)。从画图效果应该就能看出来。

 

注释:
0、用设备上下文绘图的函数,其坐标参数值都是值逻辑单位,在默认情况下,映射模式为MM_TEXT,也就是说每个逻辑单位1对应1个像素(设备单位)。


1、窗口和视口(viewport)的概念
  窗口用逻辑范围表示大小 
  视口用设备范围表示大小
  这里所谓的窗口和视图只是一种大小范围的描述方式,主要是为了理解MapMode而划分的概念


2、逻辑单位和设备单位的映射
SetWindowExt()  设定窗口的逻辑范围
SetViewportExt() 设定视口的物理大小(参数值为设备单位,也就是像素大小)

SetWindowExt 必须要和SetViewportExt结合使用,并且只用在MM_ISOTROPIC和MM_ANISOTROPIC 模式下。在MM_ISOTROPIC 模式下SetWindowExt 必须在SetViewportExt之前调用。

例如:
pDC->SetMapMode(MM_ISOTROPIC); // 等比例模式
pDC->SetWindowExt(1000, -1000); // 设置窗口设为1000*1000的矩形
pDC->SetViewportExt(500, 500);  // 设置视图设为500*500像素的矩形,
// 由此可计算出每个像素对应2个逻辑单位:
//  x坐标 1000/500  =  2, 向左为正向
//  y坐标 -1000/500 = -2, 向下为负向

同理如下代码:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(1000, 1000);
pDC->SetViewportExt(500, -500);
产生的效果是和上述代码的效果是一样的。

3、坐标原点
默认情况下,逻辑坐标原点和设备坐标原点是一致的,都是(0, 0),即窗口左上角设备坐标原点总是在左上角。

可用如下两个函数改变(移动)逻辑坐标原点:
SetWindowOrg() // 将设备坐标原点(0, 0)映射为某个逻辑坐标点
SetViewportOrg() // 将某个设备坐标点映射为逻辑坐标原点(0, 0)
SetWindowOrg 和SetViewportOrg可起到相同的效果,一般只用其中一个。

例如:
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(1000, 1000);
pDC->SetViewportExt(500, 500);  // 由此可计算出每个设备坐标单位和逻辑单位的比例是1:2

// 一下两句的效果都是一样的
pDC->SetWindowOrg(-40, -40); // 将设备坐标原点(0, 0)设置映射逻辑坐标点(-40, -40)
// pDC->SetViewportOrg(20, 20); // 将设备坐标点(20, 20)映射为逻辑坐标原点(0, 0)
// 为什么是20 呢?因为每个设备坐标单位和逻辑单位的比例是 1:2

pDC->Rectangle(0, 0, 500, 300);

 

//若需将某点(x,y)画到所设置的新的原点(0,0)上,只需使用

pDC->SetPixel(x-x,y-y,RGB(123,25,0));

//如果想画一个大点的实心点,则可以首先定义一个CBrush对象,之后将它SelectObject到pDC中,最后使用ecllipse函数。例子具体如下:

 CBrush hBrush(RGB(123,25,0)); //定义画刷
 CBrush *pOldBrush = pDC->SelectObject(&hBrush); //选到设备中去

 pDC->Ellipse(pt-10,pt-10,pt+10,pt+10); //画一个半径为10个设备单位的圆

 

//鼠标点击处pt相对于矩形rt中新原点(中心点)的位置(xpt,ypt):

 if(pt.x>rt.top && pt.yrt.top)
 {
//  xpt = (pt.x-rt.left)*(XRange/rt.width)-(XRange/rt.width)*(rt.right-rt.left)/2);
//  ypt = - ((pt.y-rt.top)*(YRange/rt.Height)-((YRange/rt.Height)*(rt.bottom-rt.top)/2));

//  AfxMessageBox(" button in rect ");
  UpdateData(FALSE);
 }

4、通过SetMapMode 函数可改变映射模式。 

5、用户坐标值和屏幕坐标值的互相转化函数
CWnd::ClientToScreen 和 CWnd::ScreenToClient

6、坐标转换函数
CDC::LPtoDP 和 CDC::DPtoLP

你可能感兴趣的:(VC/MFC)