发布时间 : 星期五 文章c++1更新完毕开始阅读e498a6cd8bd63186bcebbc63

MM_LOENGLISH 0.01英寸

MM_HIENGLISH 0.001英寸 MM_LOMETRIC 0.1mm MM_HIMETRIC 0.01mm

MM_TWIPS 1/1440英寸 //应用于打印机,一个twip相当于1/20磅,一磅又相当于1/72英寸。 看例3

//************************************************** // 例子6-3

void CMyView::OnDraw(CDC * pDC)

{

pDC->SetMapMode(MM_HIMETRIC);//设定映射模式为MM_HIMETRIC

pDC->Rectangle(CRect(0,0,4000,-4000));//画一个宽和高为4厘米的方块 }

还有一种是可变比例映射模式,MM_ISOTROPIC、MM_ANISOTROPIC。用这种映射模式可以做到当窗口大小发生变化时图形的大小也会相应的发生改变,同样当翻转某个轴的伸展方向时图象也会以另外一个轴为轴心进行翻转,并且我们还可以定义任意的比例因子,怎么样很有用吧。

MM_ISOTROPIC、MM_ANISOTROPIC两种映射模式的区别在于MM_ISOTROPIC模式下无论比例因子如何变化纵横比是1:1而M_ANISOTROPIC模式则可以纵横比独立变化。 让我们看例子4

//************************************************** // 例子6-4

void CMy002View::OnDraw(CDC* pDC) {

CRect rectClient; //

GetClientRect(rectClient);//返回客户区矩形的大小

pDC->SetMapMode(MM_ANISOTROPIC);//设定映射模式为MM_ANISOTROPIC pDC->SetWindowExt(1000,1000);

pDC->SetViewportExt (rectClient.right ,-rectClient.bottom );

//用SetWindowExt和SetViewportExt函数设定窗口为1000逻辑单位高和1000逻辑单位宽

pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2 );//设定逻辑坐标原点为窗口中心 pDC->Ellipse(CRect(-500,-500,500,500));//画一个撑满窗口的椭圆。 // TODO: add draw code for native data here }

怎么样,屏幕上有一个能跟随窗口大小改变而改变的椭圆。把 pDC->SetMapMode(MM_ANISOTROPIC);这句改为pDC->SetMapMode(MM_ISOTROPIC)会怎样?大家可以试试。那还有一个问题就是上例的比例因子是多少呢?看下面公式(注意是以例子4为例的)

x比例因子=rectClient.right/1000 //视窗的宽除以窗口范围 y比例因子=-rectClient.bottom/1000 //视窗的高除以窗口范围

从Windows的鼠标消息可以获得鼠标指针的当前坐标值(point.x和point.y)此坐标值是设备坐标。

很多MFC库函数尤其是CRect的成员函数只能工作在设备坐标下。

还有我们有时需要利用物理坐标,物理坐标的概念就是现实世界的实际尺寸。 设备坐标-逻辑坐标-物理坐标之间如何进行转换便成为我们要考虑的一个问题,物理坐标和逻辑坐标是完全要我们自己来做的,但WINDOWS提供了函数来帮助我们转换逻辑坐标和设备坐标。 CDC的LPtoDP函数可以将逻辑坐标转换成设备坐标 CDC的DPtoLP函数可以将设备坐标转换成逻辑坐标

下面列出我们应该在什么时候使用什么样的坐标系一定要记住: ◎CDC的所有成员函数都以逻辑坐标为参数 ◎CWnd的所有成员函数都以设备坐标为参数 ◎区域的定义采用设备坐标

◎所有的选中测试操作应考虑使用设备坐标。

◎需要长时间使用的值用逻辑坐标或物理坐标来保存。因设备坐标会因窗口的滚动变化而改变。

用书上的例子作为以前几篇的复习,如果你能够独立完成它说明前面的内容已经掌握。另外有些东西是新的,我会比较详细的做出说明,例如客户区、滚动窗口等。

第七篇:图形设备接口(GDI)

我想大家和我一样通过前几天的学习,对VC++MFC应用程序框架的神奇功能有了一些了解,但是还是感觉不能驾御这个强的开发工具,不过别担心,我170多斤体重不是一口吃出来的,是经过了30年不懈的努力才吃成了如此“魁梧”的体形,呵呵开个玩笑。所以学习也一样。学VC尤其如此。还有我发现很多好的技术类书籍有一个共同的特点,就是在前几章学到了一些东西在你正在疑惑或者苦苦领会的时候,接下来的章节便给你解除疑惑。雷神经验:遇到实在想不明白的地方先放下,继续向下读,也许读着读着前面的问题就明白了。『VC++技术内幕』当然属于好的技术书籍一类,所以在本书第五章开始仔细的给我们讲解设备环境类和图形设备接口(GDI),使得我们能守得云开见月明。

设备环境类CDC:

CDC是设备环境类的基类直接由CObject派生。是GDI的关键元素,它代表了物理设备。每一个C++设备环境对象都有相对应Windows设备环境,并通过一个32位类型的HDC句柄来标识。CDC类的虚拟性使我们可以很容易的做到编写同时适用于多种设备的代码。例如OnDraw函数的pDC->TextOut(0,0,\既可以适用于显示器、还可以适用于打印预览和打印,只需要在CView::OnDraw函数的pDC参数指向不同的对象类。

CClientDC和CWindowDC是显示设备环境类,都是由CDC派生而来,区别在于CClientDC是窗口的客户区不包括边框、标题栏和菜单栏,(0,0)指客户区域的左上角。CWindowDC的(0,0)指整个屏幕的左上角,这意味着我们可以在显示器的任意地方绘图,包括窗口边框、标题栏和菜单栏等等。CWindowDC一般应用在框架窗口,而不是视图窗口。

CDC对象被创建后一定要在合适的时候将它删除掉,如果忘记了删除设备环境对象则会造成内存丢失。如何做才能避免出现这个问题呢,我们应该在堆栈中构造对象。

看例子7-1

//*************************** // 例子7-1

void CMyView::OnLButtonDown(UINT nFlags,CPoint point)

{

CRect rect;

CClientDC dc(this); //在堆栈中构造设备环境对象,用一个窗口指针this作参数。

dc.GetClipBox(rect); //GetClipBox函数是一个虚函数,作用是可以获得选定区域的尺寸 }

//析构函数在函数返回时自动调用,也就完成对设备环境对象的删除。 书上还给出了另一种写法:

void CMyView::OnLButtonDown(UINT nFlags,CPoint point) {

CRect rect;

CDC * pDC=GetDC(); //通过调用CWnd的GetDC()函数获得设备环境指针 pDC->GetClipBox(rect); //可以获得选定区域的尺寸

ReleaseDC(pDC); //一定不能忘记,释放设备环境。(书上又写错了) }

创建的设备环境对象具有一些默认的特性,通过CDC类的成员函数可以设定这些特性。例如前一篇笔记用到的刷子、映射模式等等。我们还可以通过重载SelectObject函数将GDI对象选进设备环境中。

GDI对象是通过CGdiObject派生类的C++对象来表示的。读着怎么这么别扭?举例说一下。

CBrush是一个GDI的派生类,它在MFC中的层次结构是这样的:CObject派生CGdiObject派生CBrush,明白了吧。CGdiObject是所有GDI对象的抽象基类。下面列出的是GDI派生类的列表:

CBitmap:位图是一种位矩阵,每一个显示象素都对应于其中的一个或多个位,可以用来表示图象,也可以用来创建刷子

CBrush:刷子定义了一种位图形式的象素,可以用来对区域内部填充颜色。

CFont:字体是一种具有某种风格和尺寸的所有字符的完整集合,常常被作为资源,其中一些依赖某种设备。

CPalette:调色板是一种颜色映射接口,它允许应用程序在不影响其他应用程序的前提下,可以充分利用输出设备的颜色描绘能力。

CPen:笔是一种用来画线及绘制有形边框的工具,可以指定它的颜色及宽度,并可以指定画虚线、点线还是实线。

CRgn:区域是由多边形、椭圆二者组合形成的一种范围,可以用来进行填充、裁剪、鼠标点中测试等等。

以上很容易理解,可以用WINDOWS的画图帮助我们理解。

CGdiObject类很眼生,看过很多代码就没有看到过它,原因是由于CGdiObject类是所有GDI对象类的虚拟基类,所以我们不必创建CGdiObject类的对象,可以直接构造它的派生类的对象,例如这样

CPen newPen(PS_DASHDOTDOT,2,(COLORREF) 0); //黑色的笔宽度为2

但需要注意的是CFont和CRgn的对象建立需要先调用默认的构造函数来构造C++对象,然后再调用相应的创建函数如:

CreateFont或CreatePolygonRgn等。

CGdiObject类有一个虚拟的析构函数,它派生类的析构函数需要将与C++对象相关联的GDI对象删除掉,一定要在退出程序之前把构造的CGdiObject派生类对象干掉。因为一个没有释放的GDI对象会占用很多的内存。

让我们用一个例子跟踪一下GDI对象

//************************************* // 例子7-2

void CMy10View::OnDraw(CDC* pDC) {

pDC->MoveTo (10,10); pDC->LineTo (110,10);

CPen newPen(PS_DASHDOTDOT,10,(COLORREF) 192); //红色的笔宽度为10 CPen * pOldPen=pDC->SelectObject (&newPen);

//在将新对象选进设备环境的同时返回指向前一次被选对象的指针。作用保存原来的对象,以便完成任务时恢复它。

pDC->MoveTo (10,20);

pDC->LineTo (110,20);

pDC->SelectObject (pOldPen);//把原来的对象恢复 pDC->MoveTo (10,30); pDC->LineTo (110,30); }

屏幕上应该显示三条线,第一条和第三条一样颜色和粗细因为他们都是用的设备环境默认的CPen对象,第二条是一条用我们自己设定的CPen对象。我们可以看出在将新对象选进设备环境的同时返回指向前一次被选对象的指针。作用保存原来的对 象,以便完成任务时恢复它。

Windows还包含有一些可以利用的库存对象,它们不会被删除,因为Windows对企图删除它们的动作不予理睬。我们可以用SelectStockObject函数将它们选进设备环境。下面列出的是所有的有关刷子、笔、字体和调色板的库存对象。

//*************************************************************************** // MSDN中的内容

BLACK_BRUSH //Black brush. DKGRAY_BRUSH //Dark gray brush.

第八篇:颜色和字体

由于种种原因,雷神有4、5天没有看一眼VC++了,所以在开始之前我又把前几篇笔记仔细的看了一遍,使自己能够进入最佳的学习状态。因为学习状态的好坏直接影响学习的效率,有时候我看一天的书,可实际掌握的内