MFC编程案例chapter004.pdf
《MFC编程案例chapter004.pdf》由会员分享,可在线阅读,更多相关《MFC编程案例chapter004.pdf(24页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第4章 绘图在前面几章中,Wi n d o w s为我们做了所有的绘图工作从绘制一个窗口的非客户区到绘制通用控件。本章将讨论怎样用M F C的C D C类绘制控件和视图,我们将讨论:Wi n d o w s和M F C支持的绘图工具类型。Wi n d o w s和M F C支持的绘图模式和特性。两种存储为将来显示用的绘图命令的方法:元文件(M e t a f i l e)和路径(P a t h)。怎样在抖动色(dithered color)和未经抖动色(nondithered color)中绘图。什么时候Wi n d o w s绘制它的窗口。4.1 设备环境若自己编写一个函数在屏幕上画一条
2、直线,将需要以下类型的调用变量:直线坐标(起点x,y,终点x,y)。线条颜色。线条粗细。若要使功能更复杂些,还必须添加:在(像素、英寸或厘米)中指定进行绘图的度量单位的能力。在打印机或一个图形文件中绘制直线的能力。为了方便,还希望将直线绘制在任何显示器或者任何打印机上,而不必考虑显示卡或打印机的类型。如果考虑所有这些属性,该函数的结构如下:DrawLine(x1,y1,x2,y2,color,width,device,limits,units)虽然相当直观,但该函数有一个隐含的费用每当画一条直线,所有这些参数将必须压入堆栈中。同时,该函数也没有保留扩展功能的余地。要添加变量,将必须对旧函数编辑
3、任何引用。因此,怎样才能减少需要的调用变量的数目并预留扩展空间呢?一种方法是写一个包含函数所需的大多数变量的 C+类,并将该类作为一个变量进行传输。甚至可以使该类用一些合法的默认值构造自己,以便在特殊场合中使用。Wi n d o w s使用一个称为设备环境(D e v i c e Co n t e x t)的对象的方法但该对象的创建没有一个C+类,因为Wi n d o w s早于并存在于C+之外。设备环境对象用一些默认值创建,可以用它们创建默认的设备环境。应用 Wi n d o w s绘制一直线,所需的是一个设备环境对象的指针和直线坐标,设备环境对象的指针叫做设备环境句柄(H D C)。:M
4、o v e To(HDC hdc,int x,int y);:L i n e To(HDC hdc,int x,int y);要绘制一个完整的形状,:M o v e To()函数只被调用一次。然后,:L i n e To()函数被调用,没有一个多余的变量被压进堆栈(见图 4-1)。图4-1 设备环境减少调用变量的数目并预留扩展空间注意 因为设备环境在内存中创建,而内存经常受到扰动,它的地址可能是经常变化的。因此,一个设备环境句柄不是直接指向设备环境对象,而是指向另外一个跟踪设备环境地址的指针。设备无关设备环境是设备无关的,它允许你编写软件而不必指定一个设备。这些软件必须知道的是:它是编写一个设
5、备环境的,而不管该设备环境是屏幕还是 E p s o n打印机。之后,设备环境可以被分配给一个打印机、屏幕、位图或一个文件。4.2 在MFC环境中创建一个设备环境M F C用C D C类封装了一个设备环境对象,C D C的成员变量m _ h d c指向它所拥有的设备环境,用户可以创建四种类型的设备环境:屏幕。打印机。只有打印机的信息部分。位图。4.2.1 屏幕创建一个屏幕设备环境,可以用:CDC*pDC=GetDC();这里的GetDC()是C W n d类的成员函数,它返回一个允许用户绘制它的窗口客户区的设备环境;如果还希望绘制非客户区,则使用:CDC *pDC=GetWindowDC();
6、如果需要绘制整个屏幕,如编写一个屏幕保护程序或游戏程序时,可能需要对整屏进行绘制,这时使用:52第一部分 基 础 知 识下载使用设备环境以后使用设备环境以前设备环境CDC *pDC=CDC:FromHandle(:GetDC(NULL);屏幕设备环境来自三种资源之一:私有设备环境、类设备环境和通用设备环境。1.私有设备环境创建窗口时,私有设备环境便创建了,并在窗口存在期间一直存在。要使窗口创建一个私有设备环境,必须在目标窗口的窗口类中设置 C S _ O W N D C标志,这时GetDC()返回一个私有设备环境的指针,而不创建一个设备环境。在窗口存在期间,为私有设备环境所作的任何变化都被保存
7、。私有设备环境主要在以图形为中心的应用程序中使用,在那里经常地分配一个设备环境,这样会占用非常多的 C P U时间。2.类设备环境类设备环境在注册一个窗口类时创建,并在窗口类的存在期间一直存在。要使窗口类创建它自己的类设备环境,必须设置 C S _ C L A S S D C标志,GetDC()只返回指向该类设备环境的指针。此外,在窗口类的存在期间,设备环境一直保留它的值。然而,在第 1章中已提及,必须注意不要让两个由相同的窗口类创建的窗口在同一时间绘图;还应注意 M i c r o s o f t认为一个类设备环境是旧用法。3.通用设备环境在一个通用资源堆中使用 GetDC()时,一个通用设
8、备环境便创建了。要获得一个通用设备环境,不要在窗口类中设置C S _ O W N D C或C S _ C L A S S D C。对于更早版本的Wi n d o w s,操作系统本身只有五个预分配的通用设备环境,因此取名 G e t D C()与CreateDC()相对应。必须保证在用完设备环境后释放它,否则系统将发生冲突并导致异常终止。虽然设备环境是被创建的,但内存资源还是有限的,因此在使用一个通用设备环境后,仍需用下面语句释放它:ReleaseDC(pDC);注意 私有设备环境和类设备环境不必释放。用户最有可能用通用设备环境来做绘图工作。每次释放一个通用设备环境时,为它们设置的值都被丢失。
9、但是,可以用下面两个 C D C成员函数保存和恢复一个设备环境的设置值:S a v e D C()保存设备环境的当前状态。RestoreDC()将设备环境恢复到用SaveDC()保存的状态。4.2.2 打印机要为打印机创建一个设备环境,必须先创建一个 C D C类对象,然后使用它的 CreateDC()成员函数:CDC dc;dc.CreateDC(LPCTSTR lpszDriverName,LPCTSTR lpszDeviceName,LPCTSTR lpszOutput,const void*lpInitData)l p s z D r i v e r N a m e是打印机所用的设备驱
10、动程序(如“H P D RV”)。l p s z D e v i c e N a m e是进行打印的打印机设备的名字(如“HP Laserjet III”),设备驱动程序可以支持多种类型设备。第4章 绘图53下载l p s z O u t p u t指定设备的串口名(如,“L P T 1:”)。l p I n i t D a t a是任何设备专用的初始化数据。使用打印机设备环境之后,必须用 C D C类的D e l e t e D C()成员函数销毁它。但是,若在堆栈中创建C D C类,则程序返回时,设备环境自动被删除。C M y C l a s s:D r a w i n g()CDC dc
11、;d c.C r e a t e D C();/CDC object and Device Context destroyed4.2.3 内存要创建一个可以直接绘制位图的设备环境,必须先用 C D C的CreateCompatibleDC()成员函数创建一个C D C类对象。CDC dc;dc.CreateCompatibleDC(HDC hdc);CreateCompatibleDC()用设备环境的设置值初始化它所创建的设备环境对象,因此,取名兼容D C。应该从显示被创建的位图的设备(如屏幕、打印机)传递一个设备环境。要真实地绘制一个位图,还必须创建一个空位图对象,并使该设备环境与该位图相关
12、联。CDC dc;/create CDC objectCBitmap bitmap;/create CBitmap objectd c.C r e a t e C o m p a t i b l e D C(p D C);/create Device Context objectbitmap.CreateCompatibleBitmap(pDC,ICON_WIDTH,ICON_HEIGHT);/create Bitmap objectd c.S e l e c t O b j e c t(&b i t m a p);/point memory Device Context/to this bi
13、tmap绘制位图以后,必须用下列语句删除设备环境:d cDeleteDC();有关例子参见例5 8。4.2.4 信息C D C提供的最后一种设备环境类型是打印机的信息部分。CDC dc;d c.C r e a t e I C();这里的调用变量与CreateDC()中一样。信息设备环境只包含一台打印机或其他非屏幕设备的特性,如颜色支持等。创建信息设备环境的速度比创建一个常规的打印机设备环境速度快,因为它只包含设备的特性。信息使用后应当删除,与前面描述的一样。注意正如C W n d类和它控制的窗口一样,C D C类可以用Attach()把自己捆绑到一个已有的设备环境上,并可用 Detach()解
14、开自己。创建一个封装已有的设备环境的临时C D C对象,可以用FromHandle()。但是,当应用程序进入空闲循环时,这一临时类对象将被删除。54第一部分 基 础 知 识下载4.3 绘图例程C D C类还在它的成员函数中封装了全部 Wi n d o w s图形A P I,这些成员函数包括:画点的函数。画线的函数。画形状的函数。填充和翻转形状的函数。滚动屏幕的函数。绘制文本的函数。绘制位图和图标的函数。4.3.1 画点像素点的绘制不过是改变单个像素点的颜色。SetPixel()试图用指定的颜色画一个像素,返回绘制时使用的实际颜色SetPixelV()与上面的基本相同,但不用返回绘制时使用的实际
15、颜色,因而速度更快4.3.2 画线画线即改变屏幕上一系列像素点的颜色。M o v e To()开始画线、弧和多边形时,把光标移动到一个初始位置L i n e To()画一条从初始位置到另一个点的直线Arc()画一段弧A r c To()画一段弧,并更新初始位置AngleArc()画一条线,然后画一段弧,并更新初始位置PolyDraw()画一系列线段和B e z i e r样条PolyLine()画一系列线段PolyPolyLine()画多个系列线条4.3.3 画形状这里的形状是一系列封闭线条。Rectangle()画一个矩形Pie()画一个饼状楔形RoundRect()画一个圆角矩形Draw3
16、dRect()画一个三维矩形Polygon()画一个多边形DrawEdge()画一个矩形的边缘PolyPolygon()创建一个或多个多边形DrawFrameControl()画一个框架控件Ellipse()画一个椭圆4.3.4 形状填充和翻转填充和翻转改变一个形状内的所有像素点颜色。FillRect()填充一个矩形FillSolidRect()用用一单色填充一个矩形InvertRect()反转一个矩形的颜色ExtFloodFill()用用当前画刷填充一个区域,提供比FloodFill()成员函数更多的灵活性FrameRect()画一个矩形的边框第4章 绘图55下载下面三个函数包括一个区域对象
17、,它实际上是一个线条列表,形成一个由设备环境维护的形状。有关区域的详细讨论参见 4.4.8节“剪裁属性”。FillRgn()填充一个区域InvertRgn()反转一个区域的颜色FrameRgn()画一个特定区域的边框4.3.5 滚动通过滚动,可移动屏幕周围像素颜色。ScrollDC()左、右、上、下移动屏幕图像。4.3.6 绘制文本我们可能会认为文本是打印的,不是画的;但在一个图形用户界面中,甚至一个文本字符都是由像素构成的一幅图。TextOut()在在一个指定的位置,输出一个字符串E x t TextOut()在在一个矩形区域里输出一个字符串Ta b b e d TextOut()在基于用该
18、函数传输的一个表,在指定位置输出一个字符串,并将字符串中的任何制表符转换为空格D r a w Text()在在指定的矩形域里绘制文本,但比 TextOut()有更多的选项,如把文本居中和显示多行文本4.3.7 绘制位图和图标一个位图或图标只是大量像素的颜色阵列。通常有一个标题,用来指示在一行中有多少像素点,以便一个画图例程知道什么时候开始下一行。通常,位图绘制例程只是把像素阵列拷贝到视频内存中。图标具有透明色这一附加的能力,换句话说,当一个图标被绘制在屏幕上时,它的每一点的颜色都可被屏幕上原有的颜色代替。DrawIcon()在在指定的位置画一个图标BitBlt()在从指定的设备环境中拷贝一个位
19、图,通常是从磁盘中装入或在内存中创建,如前面所述StretchBlt()在与BitBlt()基本相同,但它试图伸展或压缩一个位图以适应目标PatBlt()在创建一个位模式有关绘图的例子参见第11章。4.4 绘图属性前面所讨论的所有函数都使用设备环境对象来简化它们的调用变量;因为所有的绘图函数只有一个设备环境,因此,每个函数可能只使用存储在设备环境中 2 0%的属性。一个设备环境既可以自身包含一种特定的绘图属性,也可以指向另一个包含某种特定属性的对象。例如,画一条线的属性(如宽度或颜色)可存储在一个单独的P e n对象中,而由设备环境指向该对象。有关设备环境指向的其他对象,以及封装它们的 M F
20、 C类(见图4-2)。创建这些附加的图形对象,与创建一个窗口对象的方法一样,先创建 M F C类对象,然后56第一部分 基 础 知 识下载调用那个类的成员函数 Create()。附加的图形对象一旦被创建,需要告诉设备环境运用SelectObject()使用该新对象,SelectObject()只是把设备环境指向新的图形对象。图4-2 一个设备环境可以指向包含附加绘图属性的辅助设备环境对象CPen pen;/create MFC objectp e n.C r e a t e P e n();/create Pen objectCPen*pOldPen=dc.SelectObject(&pen)
21、;/points the DC to your new object/returns a pointer to old pen object虽然设备环境指向五个不同的图形对象,但只使用一个 SelectObject()。设备环境基于对象本身的一个特征字决定替换哪个指针。用新对象绘图后,必须从内存中删除该对象。因为设备环境仍指向该对象,所以,必须先把它指向另一个对象通常是原先的对象。d c.S e l e c t O b j e c t(p O l d P e n);/select another objectp e n.D e l e t e O b j e c t();/deletes Pe
22、n object(returning/destroys the CPen object)4.4.1 设备环境属性下面的绘图属性可以在设备环境和它的辅助对象中找到:画线属性控制画线函数怎样画线(如颜色和粗细)。这些属性的大部分包含在P e n对象中。填充属性控制绘制形状的函数怎样填充形状。这些属性的大多数保存在 B r u s h对象中。文本属性控制文本是怎样绘制的。字体属性保存在 F o n t对象中,颜色和对齐方式(如左或中央)保存在设备环境中。映像属性控制x、y坐标在绘图操作中表示什么。换句话说,坐标是以像素还是以英寸为单位的,以及应采取哪一种方式。没有附加映像对象,因为所有信息都保存在设
23、备环境本身中。调色板属性可以用来控制线条和形状的颜色。图形应用程序,尤其那些视频内存有限的系统,用调色板控制颜色。所有调色板属性保存在 P a l e t t e对象中。混合属性控制线条怎样与背景互相作用。例如,是只想覆盖背景色,还是想与背景色进行X O R操作,以便以后可以用重画该线来删除它呢?剪裁属性创建一个区域,不能在该区域外绘图。这些属性保存在 R e g i o n对象中。第4章 绘图57下载CBrush类CRgn类区域对象画刷对象C B i t m a p类位图对象调色板对象C P a l e t t e类C F o n t类字体对象画笔对象C D C类C P e n类设备环境对象
24、位图属性包含在位图绘制函数中使用的位图。4.4.2 画线属性画线属性控制怎样画线条。设备环境用一个包含大多数画线属性的H P E N句柄指向一个P e n对象。在M F C中创建一个P e n对象,必须先创建一个C P e n类对象,然后,调用C P e n的两个成员函数之一。CreatePen()用用指定的颜色、宽度和模式创建一个P e n对象,模式可以是从实线到虚线的任何一种,由用户指定长线和空格的长度CreatePenIndirect()用用L P L O G P E N结构创建一个P e n对象不必创建用户自己的P e n对象,有一些预定义的P e n对象可用,可以用S e l e c
25、 t S t o c k O b j e c t()直接把它们选进设备环境中。可以用下面这些标志识别选择了哪一个存储对象。B L A C K _ P E N用包含黑画笔的属性W H I T E _ P E N用包含白画笔的属性N U L L _ P E N用使绘图函数不能画线,例如:用一个矩形画一条线,然后填充该矩形。选择该P e n对象将不能画线。4.4.3 形状填充属性B r u s h对象控制怎样填充形状。设备环境用一个 H B R U S H句柄指向一个画刷对象。若用M F C创建一个B r u s h对象,首先要创建一个 C B r u s h类对象,然后调用下面 C B r u s
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 编程 案例 chapter004
限制150内