MFC Window程序设计(第二版)精华浓缩笔记(二)

各位,看一看,瞧一瞧,新出炉的...大拍卖喽!

第二章、在窗口中画图

精华浓缩

         Windows中负责图形输出的是GDI(即Graphic Device Interface,图形设备接口)。这是Windows与硬件无关的图形输出模式的体现。GDI建立在硬件抽象层(HAL)之上,屏蔽了不同输出设备之间的差异,从而为用户提供了一个统一的“标准输出设备”。但是,与DOS不同,Windows是多任务、进程独立的,每一个窗口都应该有一个独立的输出通道。这样,GDI又使用了一种简单的机制来保证在窗口中画图的不同程序之间能共享“设备”而又互不干扰。这个机制就是DC(Device Context,设备描述表)。
     有人把DC比喻成画家的画室,这里有画布、画刷、画笔等等很多工具。

     就画布而言,画布形式可以不同,是的,我可以在桌上(desktop)的纸上(window)画,也可以就画在桌面上,还可以画在墙上(管的着吗!^_^)。
     为此,Windows MFC提供了四种不同的DC环境(封装为C++类),以标明不同的绘制权限,即:
        CPaintDC, 用于在窗口客户区画图(仅限于在OnPaint处理函数中使用);
        CClientDC, 也用于在窗口客户区画图(限于在OnPaint处理函数之外使用);
        CWindowDC, 用于在窗口内任意地方画图,包括非客户区;
        CMetaFileDC, 用于绘制GDI图元文件。

     这些类都可以直接实例化,如:
       CPaintDC dc(this);//
this表示此DC所属窗口为当前窗口
创建了一个CPaintDC对象dc。
       CWindowDC一般不常用,如果想在窗口非客户区画图,可借助OnNcPaint()处理函数捕获WM_NCPAINT消息。
    
     刚才说了,DC中还有画刷、画笔等。这些都是DC的属性,可通过DC自身(调用其成员函数)获得。
        DC属性包括文本颜色、背景颜色、映射模式、绘图模式、当前位置、当前画笔(刷)和当前字体等。
     画笔(Pen)、画刷(Brush)都是独立的GDI对象,可通过CDC成员函数SelectObject()选入DC。同样操作方式的对象还有字体(Font)、位图(Bitmap)、调色板(Palette)和区域(Region)。
     关于SelectObject():在创建好GDI对象之后,SelectObject()接收该对象指针,其返回值为先前选入DC的相同类型的对象指针(通常用来恢复DC用)。
         Windows也预先定义了一些画笔、画刷、字体以及其他一些GDI对象。这些对象称为备用对象,用CGdiObject::SelectStockObject()选入。CGdiObject是表示GDI对象的CPen、CFont等类的基类。备用对象的属性说明可以查MSDN。
     由CGdiObject派生类创建的画笔、画刷和其他对象都要占用内存资源,因此使用后一定要删除它们。处理方法与其他window对象类似。在栈中创建的对象,当此CGdiObject超出范围时会自动析构。在堆中用new创建的CGdiObject对象,可通过调用CGdiObject::DeleteObject显式删除(这会引起对GDI对象析构函数的调用)或用相应的delete运算符。如果是备用对象,则没必要专门删除,留给windows就可以了。
        VC++有一种简单的方法用来确定是否成功的删除了GDI对象:只要在调试状态下运行应用程序的调试版本即可。在应用程序结束时,没有释放的资源会显示在调试窗口中。
    
     
一些知识点

1.绘图模式:GDI将象素点输出到逻辑显示平面上时,并不只是简单的输出象素颜色,而是通过一系列布尔运算将输出象素点的颜色和输出目标位置上象素点的颜色进行合成再显示。所使用的逻辑运算关系就由DC的绘图模式确定。使用CDC:SetROP2()可更改绘图模式(ROP2,Raster Operation To)。默认绘图模式是R2_COPYPEN,直接将象素点输出到显示平面上。常用的还有R2_NOT,用于实现鼠标绘图时的Rubber技术。

2.映射模式:这是DC的属性之一,用于确定从逻辑坐标到设备坐标的转换(或者说mapping,映射)方式。设备坐标是指窗口中相应的象素点位置。单位只有象素一种。而逻辑坐标依映射模式不同而单位各异。如默认的MM_TEXT模式下,一个单位恰恰是一个象素点。MM_LOENGLISH模式下,一个单位则相当于百分之一英寸长。windows支持8种映射模式,其中的MM_ISOTROPIC和MM_ANISOTROPIC是可编程的。这意味着是用户而不是windows确定从逻辑坐标到设备坐标的转换方式。换句话说,就是用户来自行定制逻辑单位的实际大小。这两种模式最常用于根据窗口尺寸按比例自动调节画图输出大小的场合。两者之间的唯一区别在于:前者中X方向和Y方向具有同一缩放比例因子。设置映射模式的函数是CDC::SetMapMode()。

3.坐标系常用技术:
1)坐标变换:调用CDC::LPtoDP可将逻辑坐标值转换为设备坐标值。反之,调用CDC::DPtoLP可将设备坐标值转换为逻辑坐标值。在相应鼠标单击区域命中测试时,将使用这两个函数。因为鼠标单击得到的是设备坐标,而很多GDI函数使用逻辑坐标,必须转换为统一坐标,操作才有意义。
2)原点移动:默认方式下,DC的原点位于相应显示平面的左上角。MFC提供了两个CDC类成员函数,可改变原点位置。CDC::SetWindowOrg()移动窗口原点,CDC::SetViewportOrg()移动视图原点(详见MSDN)。一般只能使用两者之一。原点移动技术在边框滚动条设置时有所体现。
3)用户坐标与屏幕坐标:前者是设立在窗口客户区左上角的设备坐标值,后者是原点位于屏幕左上角的设备坐标值。两者的相互转换用函数是CWnd::ClientToScreen()和CWnd::ScreenToClient()。

4.GDI绘图函数
1)画线:包括MoveTo、LineTo、Polyline、PolylineTo、Arc、ArcTo、PolyBezier等。其中Polyline和PolylineTo都可以一次画多条线,两者的区别是PolylineTo使用DC的当前位置,而Polyline则不需要。ArcTo在win98下未实现。另外,所有GDI画线函数有一个共同特点,就是从不画最后一个象素点。
2)画图形:画封闭图形的GDI函数以外接矩形的坐标为参数。常用函数有Rectangle、Ellipse、RoundRect、Pie、Chord等。

5.画笔与画刷:在MFC中,画笔对象封装为CPen类,画刷对象封装为CBrush类。创建两者都有三种方法。最简单的就是构造一个CPen对象,直接给出所用参数进行初始化。第二种方法是调用一个未初始化的CPen对象,用CreatePen()初始化。还有一种方法是构造一个未初始化的CPen对象,通过向LOGPEN结构中填充描述画笔特性的参数,然后调用CPen::CreatePenIndirect()生成画笔。画刷基本相同。
1)CPen:windows用当前选入DC的画笔绘制线条,并给封闭图形镶制边框。画笔有三个特性,即样式、宽度和颜色。样式有PS_SOLID、PS_INSIDEFRAME、PS_NULL等。PS_NULL一般称其为“NULL画笔”,想画一个没有边框的图形,就用到它了。笔宽以逻辑单位给出,实际意义与当前映射模式相同。颜色是通过RGB宏把三个独立颜色成分的值合成为一个可传递给GDI的COLORREF值来确定的。
2)CBrush:画刷有三种基本类型,即单色、带阴影线和带图案。其中图案画刷允许用位图填充图形内部(这样,窗口背景也就没啥新鲜的了)。常用函数有
CDC::SetBkMode()、CDC::SetBkColor()等。

6.文本与字体:CDC有一打文本处理函数,重要的几个是DrawText、TextOut、GetTextMetrics、SetTextColor和SetTextAlign等。其中GetTextMetrics()传给TEXTMETRIC结构关于字体性质的相关信息。字体是一组具有特定尺寸(高度)和字样的字符;字样指示字体共有属性,如粗细等。字体封装在CFont类中,建立字体对象,要在CFont构造之后,再调用CFont的成员函数CreateFont或CreateFontIndirect等来建立GDI字体资源。针对字体,有一个LOGFONT结构,其中定义了字体的所有特性。也可通过填充它来创建字体。

后记:写这一章的笔记时有一种被作者牵着鼻子走的感觉。知识点太多,写出来有一种罗列或拼凑的嫌疑。我不希望这样,但想一想,技术也就是这样。所以我希望大家看的时候,能够思考着看,而不是记忆着看。思考着看只要求我们知道技术点、怎么用,用熟了,用多了,也就记住了。精华是浓缩的,至于如何把它化开,可要靠你自己了。

可以作为课程设计的程序,实现简单的绘图,移动图形的功能。 使用vc框架实现。 GHpaint程序的几个重点 程序的基本功能: 程序提供绘图、删除已绘图形、移动已绘图形。 可以选择绘图颜色、形状、线粗。 重点问题: 1、 程序设计基于面向对象。 程序中所有图形都从基类CShapebase派生,大部分工作(例如:删除、移动等)都在这个基类中完成。此类中的两个纯需函数: //纯需函数DrawShape,每个基类都必须实现的函数。 //指定不同图形的绘制方法。 virtual void DrawShape(CDC* pdc) = 0; //橡皮筋效果的算法函数 virtual void ZoomShape(CDC *pdc) = 0; 这两个函数需要在派生类中重载。这两个函数中主要实现不同图形的绘制方法。 也就是说,不同图形的不同点只有绘制方法不同,其他所有属性和行为都可以统一处理。 这里的继承体现了面向对象的设计,论文中可以体现这一点。 2、 动态模板库对象CPtList的使用,动态模板库基础知识。 CPtList是动态模板库的一个实例化类。功能是以链表形式保存指针,至于指针类型不做要求,需要程序员自己设计。 本程序CPtList对象中保存所有图形对象指针,由于所有图形都从CShapebase派生,所以所有图形指针都可以转化为基类CShapebase指针后保存在CPtList中。以后再遍历列表,调用图形对象函数时出现了多态调用。这里体现面向对象程序的多态,论文中可以说明。 至于CPtList的使用,可以在网上查查,可以看看程序代码,比较简单。 多态:是一种函数调用形式。出现在类继承情况下。详细的多态定义到网上查查。 程序中的多态体现在CShapebase类的虚函数,在使用CShapebase指针调用这两个虚函数,实际调用的使子类的重载函数体。这里实际上是不知道函数怎样工作,但是知道函数功能。 例如:使用CShapebase指针调用DrawShape函数,因为不知道子类是什么图形,所以不知道DrawShape怎样画这个图,但是直到DrawShape函数会把这个图画好,这就达到了要求。 3、 Windows窗口绘图基本知识。 3.1 Windows GUI绘图基本知识。使用MFC类库之后,每个窗口都有一个CDC指针量。这个变量提供图形绘制。CDC类说明查查网络,内容比较多。CDC及提供图形绘制算法,也提供各种绘制模式(单色、异或色等),提供画笔和画刷的功能。 3.2 窗口绘图基本思想: 图形绘制在窗口中,windows不会帮助程序员让图形“长在”窗口上,当窗口被遮挡,最小化后,图形绘消失。程序需要在合适的时机把图形重新画在窗口上。所以窗口上画的内容需要程序员自己思考怎样保存。在本程序中所有图形保存在CPtList对象中。 3.2 Windows为窗口提供了一个重绘消息:OnPaint,在winxp系统中,这个消息会在窗口被遮挡部分从新出现、窗口从最小化恢复时调用。在win7种只有窗口从屏幕外移动进屏幕时调用。具体情况可以查查网络,这里是我的发现,并不是主要内容。 在OnPaint消息中重新绘制所有图形是一个保证图形不消失的好办法。 4、 Windows颜色控制基本知识。 4.1 windows使用RGB三原色(红绿蓝)提供颜色控制,本程序使用24位颜色,在内存中占用4字节,所以用int型表示,但是int型的最高位字节不使用,这样每一种颜色就有一个字节表示,每种颜色级别从0-255。系统提供RGB宏帮助定义颜色,例如:RGB(255,0,0)是红色,RGB(0,0,0)黑色,RGB(255,255,255)白色。 4.2 windows绘图提供多种颜色混合模式,本程序中使用异或模式实现图形的“橡皮筋”效果和移动效果,使用纯色模式定位图形
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值