vc中默认的坐标系是MM_TEXT,即以左上角为原点,以右方当做x的正方向,以下方当做y轴的正方向。他的好处是窗口中的每一点坐标不会随着窗口的大小而改变,即你改变窗口时窗口中的图形不会改变。
如果要转为笛卡尔坐标系需要使用MM_ISOTROPIC(用户自定义X=Y)或者MM_ANISOTROPIC(用户自定义X!=Y),isotropic是相等的意思。
函数1:模式选择
int SetMapMode(
__in HDC hdc,
__in int fnMapMode
);
fnMapMode可传入MM_TEXT,MM_ISOTROPIC,MM_ANISOTROPIC等参数
函数2:设置新的高度和宽度
BOOL SetWindowExtEx(
__in HDC hdc, //设备环境句柄
__in int nXExtent, //新的宽度(如果为MM_ISOTROPIC则nXExtent和nYExtent必须相等)
__in int nYExtent, //新的高度
__out LPSIZE lpSize //用于返回原来的大小,不需要设为NULL
);
不管真实的窗口区域大小是多少,该函数告诉windows窗口的逻辑宽是nXExtent,逻辑高度是nYExtent。windows会将DC代表的区域的宽度nXExtent等分,每份的长度就是X方向上的单位长度,将高度nYExtent等分得到y轴上的单位长度
函数3:设置x,y坐标轴的方向和坐标轴的范围,即定义域和值域
BOOL SetViewportExtEx(
__in HDC hdc, //设备环境句柄
__in int nXExtent, //新的宽度(以像素为单位,定义域)
__in int nYExtent, //新的高度(以像素为单位,值域)
__out LPSIZE lpSize //用于返回原来的大小,不需要设为NULL
);
要想坐标系包含整个区域,直接把区域的真实大小传递给此函数即可。参数nXExtent和nYExtent为正表示与默认坐标系方向相同,即向右向下为X,Y的正方向,为负表示与默认方向相反
函数4:设置坐标系的原点坐标
BOOL SetViewportOrgEx(
__in HDC hdc,
__in int X, //原点横坐标
__in int Y, //原点纵坐标
__out LPPOINT lpPoint
);
演示代码1:画内切与客户区的圆(坐标系不变)
case WM_PAINT:
RECT rt;
int cx,cy;
GetClientRect(hWnd,&rt);
hdc = BeginPaint(hWnd, &ps);
cx = rt.right;
cy = rt.bottom;
//设置客户区的逻辑大小为500*500,原点为(0,0)
SetMapMode(hdc,MM_ISOTROPIC);
SetWindowExtEx(hdc,500,500,NULL);
SetViewportExtEx(hdc,cx,cy,NULL);
// SetViewportOrgEx(hdc,cx/2,cy/2,NULL);
SetViewportOrgEx(hdc,0,0,NULL);
// MoveToEx(hdc,0,0,NULL);
// LineTo(hdc,-200,-200);
Ellipse(hdc,0,0,500,500);
EndPaint(hWnd, &ps);
break;
画出的圆会随着边框的改变而改变
演示代码2:笛卡尔坐标系下画圆
case WM_PAINT:
RECT rt;
int cx,cy;
GetClientRect(hWnd,&rt);
hdc = BeginPaint(hWnd, &ps);
cx = rt.right;
cy = rt.bottom;
//设置客户区的逻辑大小为500*500,原点为中点
SetMapMode(hdc,MM_ISOTROPIC);
SetWindowExtEx(hdc,500,500,NULL);
SetViewportExtEx(hdc,cx,-cy,NULL); //设置坐标轴方向
SetViewportOrgEx(hdc,cx/2,cy/2,NULL);//设置原点
// SetViewportOrgEx(hdc,0,0,NULL);
// MoveToEx(hdc,0,0,NULL);
// LineTo(hdc,-200,-200);
Ellipse(hdc,-250,250,250,-250); //画圆
EndPaint(hWnd, &ps);
break;
注意;如果选择MM_ANISOTROPIC则会画出椭圆