Windows中的坐标系总结

来源:互联网 发布:淘宝管控记录 编辑:程序博客网 时间:2024/04/29 01:32
       许多MS-DOS是直接往视频数据存储区或者打印机端口输出数据,但此方式存在弊端在于需要每种显示卡或者打印机的驱动程序。这无疑加重了用户的负担。
        Windows为了解决这种问题,Windows提供了一种抽象接口,称为图形设备接口(GDI)。Windows已经提供了各种驱动程序。我们编写图形输出程序时就无须关心正在与我们交互的设备(如显示卡或者打印机等)。我们的程序通过GDI与设备交互。而各种GDI函数会自动参考设备环境的数据结构。
Windows程序在屏幕、打印机或其它设备上画图时,它并不是将像素直接输出到设备上,而是将图绘制到由设备描述表表示的逻辑意义上的 "显示平面" 上去。

设备描述表属性
        当使用CDC输出函数在屏幕上画图时,输出的某些特性并没有在函数调用过程中规定(采用系统默认的属性画图),但我们可以通过设备描述表自身获得或得新设置属性。MFC提供了获得和设置这些属性的函数,我们可以用这些函数方便地改变画图时的默认属性。
例如:
CDC::SetTextColor//
设置文本颜色
CDC::GetTextColor//
获得文本颜色
CDC::SetBkColor//
设置背景颜色
CDC::SetBkMode//
设置背景模式
CDC::SetMapMode//
设置映射模式
CDC::CDC::SetROP2//
设置绘图模式
CDC::MoveTo//
当前位置
CDCL::SelectObject//
当前画笔,当前画刷,当前字体

(如果想忽略背景色,可将背景设置为"Transparent",dc.SetBkMode(TRANSPARENT);

SelectObject函数
最常用来定义设备描述表属性的CDC函数是SelectObject
例如:
CPen pen(PS_SOLID,2,RGB(0,192,0));
CPen* pOldPen = dc->SelectObject(&pen);//
把新的CDC对象选入设备描述表,同时保存旧的CDC对象
dc->Ellipse(0,0,100,100);
dc.SelectObject(pOldPen);//

映射模式

默认映射模式
固定比例映射模式
可编程映射模式

简单地说,映射模式是设备描述表的属性,用于确定从逻辑坐标值到设备坐标值的转换方式

默认的映射模式

默认的映射模式使MM_TEXT,它使以象素为单位的。X轴向左为正,Y轴向下为正。默认的坐标原点在左上角。

固定比例映射模式

固定比例的映射模式有MM_LOMETRICMM_HIMETRICMM_LOENGLISHMM_HIENGLISHMM_TWIPS种。
它们默认的坐标原点都使在左上角。其区别在于每一个逻辑单位对应的物理大小不一样。
所对用的逻辑单位分别为0.1毫米,0.01毫米,0.01英寸,0.001英寸,1/1440英寸(0.0007英寸)。

可变比例映射模式(可编程映射模式)

对于可变比例的映射模式用户可以自己定义一个逻辑单位代表的大小,其大小可以任意。
也可以让这个大小随环境改变而改变。有MM_ISOTROPICMM_ANISOTROPIC这两种映射模式。
其逻辑单位的大小等于视口范围和窗口范围的比值。
两者的不同在于前者要求X轴和Y轴的度量单位必须相同,而后者没有这样的限制。

可编程映射模式
MM_ISOTROPIC
MM_ANISOTROPIC是由用户决定从逻辑坐标值转换成设备坐标值的方式,
即是由用户决定一个逻辑单位等于多少个设备单位(cm,mm,m),而不是由Windows决定。
所以被称之为可编程映射模式;
MM_ISOTROPICMM_ANISOTROPIC映射模式最常用于根据窗口尺寸按比例自动调节画图的输出大小的场合。

MM_ISOTROPICMM_ANISOTROPIC映射模式的区别
前者中X方向和Y方向具有同一个缩放比例因子,而后者两个方向可以单独缩放;

例子:
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(500,500);//
设置窗口范围,将窗口的逻辑尺寸高为500单位×500单位
dc.SetViewportExt(rect.Width(),rect.Height());//
设置视口范围
dc.Ellipse(0,0,500,500);

注:窗口的尺寸以逻辑单位计算,视口的尺寸以设备单位或像素计算。
特别说明:
MM_TEXT
为默认映射模式,其原点在窗口的左上角,X轴的正向向右,Y轴的正向向下,
并且一个逻辑单位对应于设备坐标下的一个象素

其它映射模式则原点不变,只是Y轴会翻转使正向朝上,并且逻辑单位被按比例转换为实际距离大小,而不是像素数。
需要注意的是,使用公制映射模式(非默认映射模式)时,为使输出可见,Y坐标必须为负值。
例如:
dc.Rectangle(0,0,200,100);//
默认模式下画图
dc.SetMapMode(MM_LOENGLISH);//
改变映射模式
dc.Rectangle(0,0,200,-100);//
画图

传送给CDC输出函数的是逻辑坐标值。
设备坐标值是指窗口中相应的像素点位置。

Windows中的几种坐标体系
1、屏幕坐标
屏幕坐标描述物理设备(显示器、打印机等)的一种坐标体系,
坐标原点在屏幕的左上角,X轴向右为正,Y轴向下为正。度量单位是象素。
原点、坐标轴方向、度量单位都是不能够改变的。
2、设备坐标(又称物理坐标)
设备坐标是描述在屏幕和打印机显示或打印的窗体的一种坐标体系。
默认的坐标原点是在其客户区的左上角。X轴向右为正,Y轴向下为正。
度量单位为象素。原点和坐标轴方向可以改变,但是度量单位不可以改变。
3、逻辑坐标
逻辑坐标是在程序中控制显示,打印使用的坐标体系。
该坐标系与定义的映射模式密切相关。默认的映射模式是MM_TEXT。
我们可以通过设置不同的映射模式来改变该坐标体系的默认行为。
注意:
首先,要记住两点:
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);
用GDI绘图
MFC的CDC类将相关的GDI函数封装在类成员函数中。
在设备描述表对象中或通过指向设备描述表对象的指针可以方便地调用这些函数
画线
dc.MoveTo(0,0);//设置当前位置
dc.LineTo(100,100);//指定一个线的终点位置
画圆
dc.Ellipse(0,0,100,100);
CRect rect(0,0,100,100);
dc.Ellipse(rect);
画矩形
dc.Rectangle(0,0,100,100);//画一个带直角的矩形

GDI画笔和CPen类
Windows用当前选入设备描述表的画笔绘制直线和曲线,并给用Rectangle,Ellipse以及其他图形生成函数画出的图形镶画边框。
默认画笔画出的是一个像素点宽的黑色实线。
如果要改变画线方式,则需创建一个GDI画笔,并由CDC::SelectOjbect将它选设备描述表
MFC用类CPen表示GDI画笔。
创建画笔的方法
创建画笔的最简单的方法是构造一个CPen对象并把定义画笔所用的参数都传送给该对象
CPen pen(PS_SOLID,1,RGB(255,0,0));
创建画笔的第二种方法是构造 一个汉有初始化的CPen对象并调用CPen::CreatePen:
CPen pen;
pen.CreatePen(PS_SOLID,1,RGB(255,0,0));
创建画笔的第三种方法是构造一个没有初始化的CPen对象,向LOGPEN结构中填充描述画笔特性的参数,然后调用CPen::CreatePenIndirect生成画笔
CPen pen;
LOGPEN lp;
lp.lognStyle = PS_SOLID;//样式
lp.lopnWidth.x = 1;//宽度
lp.lopnColor = RGB(255,0,0);//颜色
pen.CreatePenIndirect(&lp);
从以上的画笔定义可以看出,定义画笔需要三个特性:样式,宽度和颜色。
画笔的样式说明请参见MSDN

GDI画刷和CBrush类
在默认情况下,则Rectangle,Ellipse以及其它CDC函数画出的封闭图形填充着白色像素点。
通过创建GDI画刷并在画图之前将它选入设备描述表,可以改变图形的填充颜色。
MFC的CBrush类封装了GDI画刷。
画刷有三种基本类型:单色、带阴影和带图案。
单色画刷填充的单色。
阴影线画刷采用预先定义好的交叉线图案填充图形。
图案画刷用位图来填充图形。
创建单色画刷的方法类似于创建画笔,如下所示:
CBrush brush(RGB(255,0,0));

CBrush brush;
brush.CreateSolidBrush(RGB(255,0,0));
创建带阴影线画刷
CBrush brush(HS_DIAGCROSS,RGB(255,0,0));//阴影索引,COLORREF值

CBrush brush;
brush.CreateHatchBrush(HS_DIAGCROSS,RGB(255,0,0));
HS_DIAGCROSS是可供选择的六种阴影线样式之一,其它样式请参见MSDN
注意:
在用阴影线画刷填充时,除非用CDC::SetBkColor改变设备描述表的当前背景色,
或用CDC::SetBkMode把背景模式OPAQUE改成TRANSPARENT,禁止背景填充,
否则WIndows就以默认的背景钯(白色)填充阴影色线间的空白处。


Windows坐标系统
Windows坐标系分为逻辑坐标系和设备坐标系两种,GDI支持这两种坐标系。
一般而言,GDI的文本和图形输出函数使用逻辑坐标,而在客户区移动或按下鼠标的鼠标位置是采用设备坐标
将逻辑坐标所在的坐标系称为“窗口”;
将设备坐标所在的坐标系称为“视口”。
<1>逻辑坐标系是面向DC的坐标系,这种坐标不考虑具体的设备类型,在绘图时,Windows会根据当前设置的映射模式将逻辑坐标转换为设备坐标。
<2>设备坐标系是面向物理设备的坐标系,这种坐标以像素或设备所能表示的最小长度单位为单位,X轴方向向右,Y轴方向向下。设备坐标系的原点位置(0, 0)不限定在设备显示区域的左上角。
设备坐标系分为屏幕坐标系、窗口坐标系和客户区坐标系三种相互独立的坐标系。
 屏幕坐标系以屏幕左上角为原点,一些与整个屏幕有关的函数均采用屏幕坐              标,GetCursorPos()SetCursorPos()CreateWindow()MoveWindow()。弹出式菜单使用的也是屏幕坐标。
窗口坐标系以窗口左上角为坐标原点,它包括窗口标题栏、菜单栏和工具栏等范围。
客户区坐标系以窗口客户区左上角为原点,主要用于客户区的绘图输出和窗口消息的处理。
鼠标消息的坐标参数使用客户区坐标,CDC类绘图成员函数使用与客户区坐标对应的逻辑坐标。
2)坐标之间的相互转换
  编程时,有时需要根据当前的具体情况进行三种设备坐标之间或与逻辑坐标的相互转换
 MFC提供了两个函数CDC::DPtoLP()CDC:: LPtoDP()用于设备坐标与逻辑坐标之间的相互转换。
MFC提供了两个函数CWnd::ScreenToClient()CWnd::ClientToScreen()用于屏幕坐标与客户区坐标的相互转换。
3)映射模式
   映射模式确定了在绘制图形时所依据的坐标系,它定义了逻辑单位的实际大小、坐标增长方向,所有映射模式的坐标原点均在设备输出区域(如客户区或打印区)的左上角。此外,对于某些映射模式,用户还可以自定义窗口的长度和宽度,设置视图区的物理范围。
映射方式定义了Windows如何将GDI函数中指定的逻辑坐标映射为设备坐标
 Windows定义了8种映射模式,见下表。
 映射模式使得程序员可不必考虑输出设备的具体设备坐标系,而在一个统一的逻辑坐标系中进行图形的绘制。

映射方法(Mapping Mode

逻辑单位

坐标轴方向

MM_TEXT(默认方式)

1 pixel

X轴正方向朝右,Y轴正方向朝下

MM_LOMETRIC

0.1 mm

X轴正方向朝右,Y轴正方向朝上

MM_HIMETRIC

0.01 mm

X轴正方向朝右,Y轴正方向朝上

MM_LOENGLISH

0.01 inch

X轴正方向朝右,Y轴正方向朝上

MM_HIENGLISH

0.001 inch

X轴正方向朝右,Y轴正方向朝上

MM_TWIPS

1/1440 inch

X轴正方向朝右,Y轴正方向朝上

MM_ISOTROPIC

自定义(X=Y)

自定义

MM_ANISOTROPIC

自定义(X!=Y)

自定义


当绘制的图形需要随着窗口的大小改变而自动改变的时候,一般选择MM_ISOTROPICMM_ANISOTROPIC映射方式。它们的唯一区别就是前者的X轴和Y轴的逻辑单位的大小是相同的,单词“isotropic”就是各个方向相等的意思,此映射方式适合绘制圆或正方形。而实际应用中,常常给X轴和Y轴取不同的比例,这时候选择MM_ANISOTROPIC映射方式。单词“anisotropic”就是各个方向相异的意思。
(4)自定义映射模式
“窗口”和“视口”的概念:
窗口(Window):对应逻辑坐标系上程序员设定的区域
视口(Viewport):对应实际输出设备上程序员设定的区域
窗口原点是指逻辑窗口坐标系的原点在视口(设备)坐标系中的位置;
视口原点是指设备实际输出区域的原点。
除了映射模式,窗口和视口也是决定一个点的逻辑坐标如何转换为设备坐标的一个因素。一个点的逻辑坐标按照如下式子转换为设备坐标:
设备(视口)坐标 = 逻辑坐标 窗口原点坐标  + 视口原点坐标

//定义坐标映射方式

WINGDIAPI int   WINAPI SetMapMode(HDC, int);

API函数在MFC中封装为CDC::virtual int SetMapMode(int nMapMode);

//定义逻辑窗口区域,单位为逻辑单位(Logical

WINGDIAPI BOOL  WINAPI SetWindowExtEx (HDC, int, int, LPSIZE);

API函数在MFC中封装为CDC::virtual CSize SetWindowExt(int cx, int cy);

//设置逻辑窗口的原点坐标,缺省原点为(00)。

WINGDIAPI BOOL  WINAPI SetWindowOrgEx(HDC, int, int, LPPOINT);

API函数在MFC中封装为CDC::CPoint SetWindowOrg(int x, int y);

注意:SetWindowOrg(Ex) 只有在映射模式为MM_ANISOTROPICMM_ISOTROPIC时才有意义。

//定义视口的坐标轴方向及区域、定义域和值域,单位为像素(Pixel

WINGDIAPI BOOL  WINAPI SetViewportExtEx(HDC, int, int, LPSIZE);

API函数在MFC中封装为CDC::virtual CSize SetViewportExt(int cx, int cy);

注意:SetViewportExt(Ex) 只有在映射模式为MM_ANISOTROPICMM_ISOTROPIC时才有意义。

//设置视口的原点坐标,缺省原点为(00)。

WINGDIAPI BOOL  WINAPI SetViewportOrgEx(HDC, int, int, LPPOINT);

API函数在MFC中封装为CDC:: virtual CPoint SetViewportOrg(int x, int y);