(1)Windows坐标系统
Windows坐标系分为逻辑坐标系和设备坐标系两种,GDI支持这两种坐标系。一般而言,GDI的文本和图形输出函数使用逻辑坐标,而在客户区移动或按下鼠标的鼠标位置是采用设备坐标。
<1>逻辑坐标系(Logical Coordinate)是面向DC的坐标系,这种坐标不考虑具体的设备类型,在绘图时,Windows会根据当前设置的映射模式将逻辑坐标转换为设备坐标。
<2> 设备坐标(Device Coordinate)又称为物理坐标(Physical Coordinate),是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位 置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角,不限定在设备显示区域的左上角。
设备坐标系分为屏幕坐标系、窗口坐标系和客户区坐标系三种相互独立的坐标系。
- 屏幕坐标系以屏幕左上角为原点,一些与整个屏幕有关的函数均采用屏幕坐标,如GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()。弹出式菜单使用的也是屏幕坐标。
- 窗口坐标系以窗口左上角为坐标原点,它包括窗口标题栏、菜单栏和工具栏等范围。
- 客户区坐标系以窗口客户区左上角为原点,主要用于客户区的绘图输出和窗口消息的处理。鼠标消息的坐标参数使用客户区坐标,CDC类绘图成员函数使用与客户区坐标对应的逻辑坐标。
下面三种都是显示设备的物理坐标,它们在屏幕上用真实的物理像素表示
- 屏幕坐标 Screen coordinates: 原点(0,0)位于屏幕的左上角
- 窗口坐标 Window coordinates: 原点(0,0)位于窗口的左上角(包括非客户区,如标题条)
- 客户区坐标 Client-window coordinates: 原点(0,0)位于客户窗口的左上角
逻辑坐标是GDI函数在屏幕上显示数据所用的坐标,逻辑坐标除非与物理坐标相关联,否则没有义。windows依靠映射模式解释逻辑坐标。比如缺省的模式为MM_TEXT,该模式下,物理坐标与逻辑坐标是一对一的关系。
逻辑坐标(Logical Coordinate)是系统用作记录的坐标。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来 表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。逻辑坐标和设备坐标即使在缺省模式下其数值也未必一致,除了在以下两种情况下:
1. 窗口为非滚动窗口
2. 窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。
在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻 坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标,可以使用CDC 函数DptoLP()将设备坐标转化为逻辑坐标,同样可以用LptoDP()将逻辑坐标转化为设备坐标。
(2)坐标之间的相互转换
编程时,有时需要根据当前的具体情况进行三种设备坐标之间或与逻辑坐标的相互转换。
MFC提供了两个函数CDC::DPtoLP()和CDC:: LPtoDP()用于设备坐标与逻辑坐标之间的相互转换。
MFC提供了两个函数CWnd::ScreenToClient()和CWnd::ClientToScreen()用于屏幕坐标与客户区坐标的相互转换。
(3)映射模式
映射模式确定了在绘制图形时所依据的坐标系,它定义了逻辑单位的实际大小、坐标增长方向,所有映射模式的坐标原点均在设备输出区域(如客户区或打印区)的左上角。此外,对于某些映射模式,用户还可以自定义窗口的长度和宽度,设置视图区的物理范围。
Windows定义了8种映射模式,见下表。
注意:
首先,要记住两点:
1。设备坐标的(0, 0)点始终是客户区的左上角。
2。我们在绘图时指定的点全部都是逻辑坐标点。
坐标转换
调用CDC::LPtoDP可以将逻辑坐标转换为设备坐标;
高用CDC::DPtoLP可以将设备坐标转换为逻辑坐标;
什么时候用什么坐标系
可以认为CDC的所有成员函数都以逻辑坐标作为参数
可以认为CWnd的所有成员函数都以设备坐标作为其参数
所有选中测试操作中都应该考虑设备坐标。区域的定义应采用设备坐标。
某些像CRect::PtInRect之类的函数只有在采用设备坐标参数时才会保证有正确的结果
将一些需要长期使用的值用逻辑坐标或物理坐标来保存。 如果用逻辑坐标来保存某点的坐标的话,那么只要用户对窗口进行一下滚动,该点的坐标就不再有效了。
鼠标单击事件下得到的坐标都是设备坐标!
移动原点
CDC::SetViewportOrg()移动视口的原点 CDC::SetWindwosOrg()移动窗口的原点
正常情况下,只能使用其中之一,同时使用两个会搞提一团糟。
获取设备信息 获得系统分辨率
CClientDC dc(this);
int cx = dc.GetDeviceCaps(HORZRES);
int cy = dc.GetDeviceCaps(VERTRES);