http://blog.csdn.net/afterruins/archive/2008/09/14/2839062.aspx
逻辑坐标和设备坐标:
设备坐标(Device Coordinate)又称为物理坐标(Physical Coordinate),是指输出设备上的坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。
逻辑坐标(Logical Coordinate)是系统用作记录的坐标。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。逻辑坐标和设备坐标即使在缺省模式下其数值也未必一致,除了在以下两种情况下:
1. 窗口为非滚动窗口
2. 窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。
注:逻辑坐标就是文档的坐标,设备坐标就是视图的坐标.视图就是响应消息和查看文档用的.文档一般比视图大,视图只能够查看一部分文档,拖动滚动条,在视图中显示的那部分文档改变了,所以此时的鼠标下面的逻辑坐标也跟着改变了。在没有拖动滚动条的时候,逻辑坐标和设备坐标是一致的,一拖动滚动条,逻辑坐标相对于设备坐标有了位移.
下面列出我们应该在什么时候使用什么样的坐标系一定要记住:
◎CDC的所有成员函数都以逻辑坐标为参数
◎CWnd的所有成员函数都以设备坐标为参数
◎区域的定义采用设备坐标
◎所有的选中测试操作应考虑使用设备坐标。
◎需要长时间使用的值用逻辑坐标或物理坐标来保存。因设备坐标会因窗口的滚动变化而改变。
eg:
在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标.
CDC的LPtoDP函数可以将逻辑坐标转换成设备坐标
CDC的DPtoLP函数可以将设备坐标转换成逻辑坐标
映射模式:
在windows下,一共有三大类影射模式.
映 射 方 式 |
逻 辑 单 位 |
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影射模式:在此模式下,向右移动,x增加,向下移动,y增加.因为此模式和设备坐标相似,因此,默认情况下,windows使用的是此模式.
示例:
pDC->Rectangle(CRect(0,0,200,200));//全部采用默认画一个宽和高为200象素的方块
//**************************************************
pDC->SetMapMode(MM_TEXT);//设定映射模式为MM_TEXT
pDC->SetWindowOrg(CPoint(100,100));//设定逻辑坐标原点为(100,100)
pDC->Rectangle(CRect(100,100,300,300));//画一个宽和高为200象素的方块
这两个例子显示出来的图形是一样的,都是从屏幕左上角开始的宽和高为200象素的方块,可以看出例子2将逻辑坐标(100,100)映射到了设备坐标(0,0)处,这样做有什么用?滚动窗口使用的就是这种变换。
固定比例的影射模式:
固定比例的映射模式又分:
(1)MM_LOENGLISH 0.01英寸
(2)MM_HIENGLISH 0.001英寸
(3)MM_LOMETRIC 0.1毫米
(4)MM_HIMETRIC 0.01毫米
(5)MM_TWIPS 1/1440英寸
此模式下,向右移动,x增加;向下移动,y减少.
示例:
pDC->SetMapMode(MM_HIMETRIC);//设定映射模式为MM_HIMETRIC
pDC->Rectangle(CRect(0,0,4000,-4000));//画一个宽和高为4厘米的方块
可变比例模式:
可变比例模式分为两种,MM_ISOTROPIC和MM_ANISOTROPIC.他们允许我们改变比例因子和原点。使用MM_ISOTROPIC 模式时,将始终保持1:1的纵横比.换句话说,无论比例因子如何变,圆始终是个圆.在MM_ANISOTROPIC方式中.x和y比例因子可以分别改变.圆可以压成椭圆.
示例:
CRect rectClient;
GetClientRect(rectClient);//获得客户区
pDC->SetMapMode(MM_ANISOTROPIC);//设定映射模式为MM_ANISOTROPIC
pDC->SetWindowExt(1000,1000);
pDC->SetViewportExt (rectClient.right ,-rectClient.bottom );
//SetWindowExt:设定窗口范围,以逻辑单位计算.
//SetViewportExt:设定视口范围,以设备单位计算.
pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2 );
//设定逻辑坐标原点为窗口中心
pDC->Ellipse(CRect(-500,-500,500,500));//画一个撑满窗口的椭圆。
示例程序:转换到MM_HIMETRIC映射模式
在OnprepareDC中设置映射模式要比在OnDraw中更合适些。
1、通过类向导重载虚函数OnPrepareDC
void C*View::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode(MM_HIMETRIC);
CView::OnPrepareDC(pDC, pInfo);
}
应用程序框架在调用OnDraw前会先调用OnPrepareDC虚函数。
2、编辑视图中的构造函数
CEx3View::CEx3View():m_rectEllipse(0,0,4000,-4000)
{
m_nColor = GRAY_BRUSH;
}
3、编辑OnLButtonDown函数
为了进行点测试,必须把椭圆矩形转化为设备坐标。
void CEx3View::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
CRect rectDevice = m_rectEllipse;
dc.LPtoDP(rectDevice);
if(rectDevice.PtInRect(point))
{
if(m_nColor == GRAY_BRUSH)
{
m_nColor = GRAY_BRUSH;
}else{
m_nColor = GRAY_BRUSH;
}
InvalidateRect(rectDevice);
}
}
为了进行点测试,该函数必须把椭圆矩形转换为设备坐标。