http://blog.csdn.net/nolatin/article/details/8764063
//map the logical point (0,0) to the device point (xViewOrg, yViewOrg)
SetViewportOrgEx ( hdc, xViewOrg, yViewOrg, NULL)
This is related to the SetWindowOrgEx function. Generally, you will use one function or the other, but not both. Regardless of your use of SetWindowOrgEx and SetViewportOrgEx, the device point (0,0) is always the upper-left corner.
调用SetMapMode(MM_ANISOTROPIC)时,逻辑描画領域坐标系的原点与画面的左上角是重叠的。然后需要调用SetWindowExt()函数和SetViewportExt()函数,来设定纵轴横轴的単位和方向以及伸缩比例。
virtual CSize SetWindowExt(int cxWindow, int cyWindow);
virtual CSize SetViewportExt(int cxViewport, int cyViewport);
一般说SetWindowExt()函数和SetViewportExt()函数要成对调用。它们的意思(功能)是:用cxViewport个物理像素来表现cxWindow个逻辑点(数学上的长度)。同样用cyViewport个物理像素来表现cyWindow个逻辑点(数学上的长度)。cx和cy看起来好像是为了设定描画範囲参数,其实不然。很简单,它们是代表逻辑长度与物理长度的比值的分子和分母。正负符号也可以设定。当cxViewport/cxWindow为正的情况下,X軸的方向是指向右方,反过来指向左方。 cyViewport/cyWindow为正的情况下,Y軸的方向是指向上方,反过来指向下方。
例:用全部用户区描画一个+-110的直角坐标系。
void CVwporttestView::OnDraw(CDC* pDC)
{
CRect rect;
GetClientRect (&rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(220, -220);
pDC->SetViewportExt(rect.Width(), rect.Height());
pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
pDC->MoveTo(-110, 0); pDC->LineTo(110, 0);
pDC->MoveTo(0, -110); pDC->LineTo(0, 110);
for (int i = -100; i <= 100; i += 10)
{
pDC->MoveTo(i, 2); pDC->LineTo(i, -2);
pDC->MoveTo(2, i); pDC->LineTo(-2, i);
CString strText;
strText.Format("%+d", i);
pDC->TextOut(i, -2, strText);
pDC->TextOut(5, i+4, strText);
}
}
2. SetWindowExt设定窗口尺寸,SetViewportExt设定视口尺寸。 窗口尺寸以逻辑单位计算,视口尺寸以物理单位计算。
CRect rectClient;
GetClientRect(rectClient);// 取窗口物理尺寸(单位:像素)
pDC-> SetMapMode(MM_ANISOTROPIC);
pDC-> SetWindowExt(1000, 1000);//窗口逻辑大小:1000*1000,
pDC-> SetViewportExt(rectClient.right, -rectClient.bottom);//改变Y坐标方向--viewport使用物理大小
pDC-> SetViewportOrg(rectClient.right/2, rectClient.bottom/2);//设置窗口中心点为坐标系原点--Viewport使用物理大小
pDC-> Ellipse(CRect(-500, -500, 500, 500));//以逻辑单位画图---普通GDI API使用逻辑单位
默认方式下,物理/逻辑值是1:1关系,可换用。但使用SetWindowExt/SetViewportExt后两者不可混用。