详解VC++中的窗口与视口

时间:2022-10-13 10:39:34

在VC++的学习中,窗口(Window)与视口(Viewport)一向是初学者较难理解的难点,也是容易混淆的地方,本文从多个方面讲述VC++中窗口与视口的异同,以方便读者更准确,更全面的掌握窗口与视口的相关知识,为计算机绘图带来便利。

基于VC++的GDI常用坐标系统

数据显示和图形绘制都需要在相应的坐标系中才能精确完成。在计算机绘图中,常用的坐标系分为设备坐标和逻辑坐标两种。

1.设备坐标

设备坐标是与设备高度相关的坐标,在VC++中的设备坐标系统中,单位用的是像素点,X值从左到右增大,Y值从上到下增大。

为满足各种不同需要,在VC++中又细分了以下3种设备坐标

(1)全窗口坐标。主要包括Windows程序中的窗口、滚动条、窗口框、标题条、菜单等。在将逻辑单位转换成窗口坐标的过程中,可以通过GetWindowDC函数获取窗口设备环境。

(2)屏幕坐标。范围包括整个显示器屏幕,屏幕的左上角为(0,0)。屏幕坐标和全窗口坐标包括的对象是不一样的,屏幕坐标包含的对象是硬件外部设备,全窗口坐标包含的对象是Windows程序软件。

(3)客户区域坐标。指Windows应用程序的客户区域,客户区域的左上角为(0,0)。屏幕区域坐标和客户区域坐标相互转换的函数为ScreenToClien和ClientToScreen。

2.逻辑坐标

逻辑坐标不依赖于于设备,即它与设备的类型无关,也与设备具体的点阵密度大小无关。在逻辑坐标中使用逻辑单位,计算机绘图中GDI函数LineTo在画出直线的时候,用户是不需要考虑输出设备的相关参数的。

窗口和视口

数据显示和图形绘制并不是直接在屏幕上进行的,而是首先将图形绘制到一个具有逻辑坐标系的虚拟窗口中,然后再根据预先设置好的映射模式,将虚拟窗口中的图形或图像映射到屏幕或打印机等设备中。这个虚拟的窗口被称作窗口(window)。显示图像的设备就是视口(Viewport),对应着实际的屏幕或打印机。

逻辑坐标所在的坐标系称为“窗口”,窗口是基于逻辑坐标,其坐标单位可以是毫米、厘米、像素点,或其他尺度,与显示设备无关。窗口与视口为同一区域,它的x轴向右,y轴向上。

设备坐标的坐标系称为“视口”。视口是基于设备坐标,与显示设备有关,视口类似于客户区坐标,在使用GetWindowDC或CreateDC函数获取设备环境后,视口也可以指屏幕坐标或全窗口坐标。视口是和窗口等同的一块矩形区域,它的x轴向右和y轴向下。视口是窗口的按比例的映像(投影)。

用于设置窗口的函数:SetWindowsOrg和SetWindowExt,用于设置视口的函数:SetViewportOrg和SetViewportExt。

窗口和视口实际上描述的是同一个客观场景,它们之间的区别仅仅在于两者坐标系的单位不同。窗口和视口定义了这两个坐标系统的比例关系,在程序作图时,使用的坐标总是窗口坐标,而实际的显示或输出设备却各有自己的坐标。

映射模式

映射模式的意思是在屏幕或者打印机上绘图的时候,可以使用英寸或者毫米作为单位,这样更加直观。其中要注意设备单位和逻辑单位的区别:逻辑单位是传递给绘图函数的x和y值,它们可以表示英寸和毫米,而设备单位是x和y在屏幕上的像素数,或是打印机上的点阵数。

映射模式决定了Windows将怎样把GDI函数中指定的逻辑坐标映射为设备坐标。通过设置映射方式,可以设置窗口下的逻辑坐标系的长度单位和坐标的正方向。在计算机绘图时,Windows会将逻辑坐标转换成设备坐标,而逻辑坐标和设备坐标的转换是由映射模式决定的。映射模式通过设备环境类的一个成员函数SetMapMode()来设置。设置映射模式后,坐标值会传给绘图函数,然后通过Windows映射模式转换成设备坐标。如果要从设备环境得到当前的映射模式可以使用GetMapMode()函数

Windows定义的8种映射模式可以分为三类。

第一类:MM_TEXT,默认的映射模式,把设备坐标映射到像素。坐标原点是屏幕左上角(0,0)。

第二类:MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS,这是一组固定比例映射模式。它们之间的区别在于比例因子不同。

第三类:可变比例映射模式,MM_ISOTROPIC和MM_ANISOTROPIC。这两种映射模式允许改变比例因子和原点。使用MM_ISOTROPIC时,x和y始终保持1:1的比例。

值得注意的是,使用MM_TEXT映射模式时候,y轴是垂直向下增大的,x轴是向右增大的。而其他映射模式的y轴是沿屏幕向上增大的,x轴在几种模式中都相同是向右增大的。

窗口坐标与视口坐标的转换

设备坐标和逻辑坐标可以看成是两个互相平行的坐标系。设备坐标的单位为像素,逻辑坐标的单位为mm、inch、twip等。两种坐标的原点(0,0)的垂影重合,x轴从左到右增大,y轴从上到下增大。

在调用函数时使用的(x,y)坐标点为逻辑坐标点,通过以下两个公式可以将逻辑点转换为设备点

xViewport=(xWindow-xWinOrg)*

(xViewExt/xWinExt)+xViewOrg

yViewport=(yWindow-yWinOrg)*

(yViewExt/yWinExt)+yViewOrg

该公式还可以写为:

设备x=逻辑x*x比例因子+x原点偏移量

设备y=逻辑y*y比例因子+y原点偏移量

其中

(Xviewport-Xvieworg)/(Xwindow-Xwinorg)=Xviewext/Xwinext; (Yviewport-Yvieworg)/(Ywindow-Xwinorg)

=Yviewext/Ywinext;

逻辑坐标单位与设备坐标单位的比,即为比例因子。

为了适应不同映射模式,函数Set Viewport OrgEx和Set Window OrgEx被Windows用来设置设备坐标系和逻辑坐标系的映射方式。注意这里不是设置视口和窗口的原点,因为设备坐标原点和逻辑坐标原点是不会变化的。

逻辑坐标系和设备坐标系是通过窗口原点和视口原点发生联系的,当图像各点从逻辑坐标系向设备坐标系映射时,根据坐标之间的换算关系,换算成图像各点在设备坐标系中相对于视口原点的位置,实现坐标映像。

窗口原点、视口原点、逻辑原点和设备原点

逻辑坐标原点可以看做是窗口中的一个固定的点。通过这个点,引出两条坐标线,建立逻辑坐标系,长度单位和正方向则通过SetMapMode来设置。

窗口原点只是逻辑坐标系中一个可变点,这个点的坐标是通过SetWindowOrg来设置的。

设备坐标原点可以看做是视口中的一个固定点。对于屏幕而言,它位于左上角,通过这个点建立设备坐标系,长度单位是像素,X轴向右为正,Y轴向下为正。

视口原点是设备坐标系中的一个可变点,这个点的坐标通过SetViewportOrg来设置。

默认的窗口原点和视口原点都为(0,0),是可以改变的。默认的窗口范围和视口范围均为(1,1),则不可改变。对于同一个图形,用窗口坐标系统表达的该区域的长和宽与视口坐标系统表达的长和宽是不同的。

窗口和视口中的场景必须通过映射模式正确地显示到设备环境中。窗口坐标的原点与视口坐标的原点始终对应于同一点,注意该点坐标(不管是视口坐标原点,还是窗口坐标原点)不一定为(0,0)。但是,默认情况下,窗口坐标原点、视口坐标原点还是重合在一起的,都是在设备点(0,0)处。WindowsGDI的设备环境原点是位于屏幕的左上角,设备点始终位于(0,0)点。

通过不同的映射方式,可以用逻辑单位改变窗口原点的位置而将物体显示在设备环境中,也可以在以像素为单位的视口坐标系下移动视口将物体显示在显示屏上。不管对窗口和视口原点作什么改变,设备点(0,0)始终在客户区的左上角,两者都是为了让物体在显示屏上显示。调整窗口原点和调整视口原点可以达到相同的效果。

映射方向是由窗口原点映射到视口原点,即无论你窗口的原点和视口的原点怎么变,窗口的原点总是映射到视口的原点。

无论利用函数(如:SetViewportOrgExt和SetWindowOrgEx)对窗口和视口的原点做怎样改变,设备点(0,0)始终在客户区的左上角。

滚动窗口的处理

对于定义的客户区域大于程序所创建的窗口时,就需要有滚动条来滚动显示,才能显示完整的客户区域。

假设未滚动窗口时,客户区左上角对应窗口和视口的原点坐标,且默认均为(0,0),如果滚动窗口时,水平方向向右滚动了X个像素,垂直方向向下滚动了Y个像素,则应该认为客户区域的左上角为窗口原点(同时也是视口原点)一起滚动,并且窗口原点(同时也是视口的原点)的坐标始终为(0,0)不变,变的只是窗口原点在设备环境坐标系中的位置。设备环境的坐标系永远不会移动。通过SetViewportOrgEx(X,Y)实现将世界坐标系的原点移到显示屏的(X,Y)位置。这两种移动有个相同的结果就是窗口坐标的原点与视口坐标的原点始终对应于同一点,而新的世界坐标系的原点位置恰好是设备环境中的(X,Y)。通过调试MFC中CSrollView类函数发现,它就是通过SetViewportOrgEx(X,Y)函数移动世界坐标系的原点,从而实现“窗口的滚动”。

综上所述,窗口、视口是相互对应的概念,既有联系又有区别。只有全面了解了窗口与视口的概念,才能更好地掌握窗口与视口的异同,才能更加灵活地进行窗口与视口的转换。

上一篇:人文教育与医学职业素质教育关系的研究 下一篇:中职数学教学与专业课相结合的教学新模式初探