《图形文本和位图.pptx》由会员分享,可在线阅读,更多相关《图形文本和位图.pptx(83页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、7.1.2 坐标映射在讨论坐标映射之前,先来看看下列语句:pDC-Rectangle(CRect(0,0,200,200);它是在某设备环境中绘制出一个高为200个像素,宽也为200个像素的方块。由于默认的映射模式是MM_TEXT,其逻辑坐标(在各种映射模式下的坐标)和设备坐标(显示设备或打印设备坐标系下的坐标)相等。因此这个方块在1024 x 768的显示器上看起来要比在640 x 480的显示器上显得小一些,而且若将它打印在600dpi精度的激光打印机上,这个方块就会显得更小了。如表7.1所示。表7.1 映射模式第1页/共83页7.1.2 坐标映射例Ex_Draw 通过设置窗口和视口大小来
2、改变显示的比例(1)用MFC AppWizard创建一个默认的单文档应用程序Ex_Draw。(2)在CEx_DrawView:OnDraw函数中添加下列代码:void CEx_DrawView:OnDraw(CDC*pDC)CEx_DrawDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);CRect rectClient;GetClientRect(rectClient);/获得当前窗口的客户区大小pDC-SetMapMode(MM_ANISOTROPIC);/设置MM_ANISOTROPIC映射模式pDC-SetWindowExt(1000,1000);/设
3、置窗口范围pDC-SetViewportExt(rectClient.right,-rectClient.bottom);/设置视口范围pDC-SetViewportOrg(rectClient.right/2,rectClient.bottom/2);/设置视口原点pDC-Ellipse(CRect(-500,-500,500,500);第2页/共83页例Ex_Draw(3)编译运行,结果如图7.1所示。图7.1 改变显示比例第3页/共83页7.1.3 CPoint、CSize和CRect在图形绘制操作中,常常需要使用MFC中的CPoint、CSize和CRect等简单数据类由于CPoint
4、(点)、CSize(大小)和CRect(矩形)是对Windows的POINT、SIZE和RECT结构的封装,因此它们可以直接使用各自结构的数据成员,如下所示:typedef struct tagPOINT typedef struct tagSIZE LONG x;/点的x坐标 int cx;/水平大小 LONG y;/点的y坐标 int cy;/垂直大小 POINT;SIZE;typedef struct tagRECT LONG left;/矩形左上角点的x坐标 LONG top;/矩形左上角点的y坐标 LONG right;/矩形右下角点的x坐标 LONG bottom;/矩形右下角点的
5、y坐标 RECT;第4页/共83页7.1.3 CPoint、CSize和CRect1.CPoint、CSize和CRect类的构造函数CPoint类带参数的常用构造函数原型如下:CPoint(int initX,int initY);CPoint(POINT initPt);其中,initX和initY分别用来指定CPoint的成员x和y的值。initPt用来指定一个POINT结构或CPoint对象来初始化CPoint的成员。CSize类带参数的常用构造函数原型如下:CSize(int initCX,int initCY);CSize(SIZE initSize);其中,initCX和init
6、CY用来分别设置CSize的cx和cy成员。initSize用来指定一个SIZE结构或CSize对象来初始化CSize的成员。CRect类带参数的常用构造函数原型如下:CRect(int l,int t,int r,int b);CRect(const RECT&srcRect);CRect(LPCRECT lpSrcRect);CRect(POINT point,SIZE size);CRect(POINT topLeft,POINT bottomRight);第5页/共83页7.1.3 CPoint、CSize和CRect2.CRect类的常用操作由于一个CRect类对象包含用于定义矩形的
7、左上角和右下角点的成员变量,因此在传递LPRECT、LPCRECT或RECT结构作为参数的任何地方,都可以使用CRect对象来代替。CRect类的操作函数有很多,这里只介绍矩形的扩大、缩小以及两个矩形的“并”和“交”操作,更多的常用操作如表7.2所示。表7.2 CRect类常用的成员函数第6页/共83页7.1.3 CPoint、CSize和CRect2.CRect类的常用操作成员函数InflateRect和DeflateRect用来扩大和缩小一个矩形。由于它们的操作是相互的,也就是说,若指定InflateRect函数的参数为负值,那么操作的结果是缩小矩形,因此下面只给出InflateRect函
8、数的原型:void InflateRect(int x,int y);void InflateRect(SIZE size);void InflateRect(LPCRECT lpRect);void InflateRect(int l,int t,int r,int b);其中,x用来指定扩大CRect左、右边的数值。y用来指定扩大CRect上、下边的数值。size中的cx成员指定扩大左、右边的数值,cy指定扩大上、下边的数值。lpRect的各个成员用来指定扩大每一边的数值。l、t、r和b分别用来指定扩大CRect左、上、右和下边的数值。第7页/共83页7.1.3 CPoint、CSize和
9、CRect2.CRect类的常用操作成员函数IntersectRect和UnionRect分别用来将两个矩形进行相交和合并,当结果为空时返回FALSE,否则返回TRUE。它们的原型如下:BOOL IntersectRect(LPCRECT lpRect1,LPCRECT lpRect2);BOOL UnionRect(LPCRECT lpRect1,LPCRECT lpRect2);其中,lpRect1和lpRect2用来指定操作的两个矩形。例如:CRect rectOne(125,0,150,200);CRect rectTwo(0,75,350,95);CRect rectInter;re
10、ctInter.IntersectRect(rectOne,rectTwo);/结果为(125,75,150,95)ASSERT(rectInter=CRect(125,75,150,95);rectInter.UnionRect(rectOne,rectTwo);/结果为(0,0,350,200)ASSERT(rectInter=CRect(0,0,350,200);第8页/共83页7.1.4 颜色和颜色对话框在MFC中,CDC使用的是RGB颜色空间,即选用红(R)、绿(G)、蓝(B)三种基色分量,通过对这三种基色不同比例的混合,可以得到不同的彩色效果。并且,MFC使用COLORREF数据类
11、型来表示一个32位的RGB颜色,它也可以用下列的十六进制表示:0 x00bbggrr 此形式的rr、gg、bb分别表示红、绿、蓝三个颜色分量的16进制值,最大为0 xff。在具体操作RGB颜色时,还可使用下列的宏操作:GetBValue 获得32位RGB颜色值中的蓝色分量 GetGValue 获得32位RGB颜色值中的绿色分量 GetRValue 获得32位RGB颜色值中的红色分量 RGB 将指定的R、G、B分量值转换成一个32位的RGB颜色值。MFC的CColorDialog类为应用程序提供了颜色选择通用对话框,如图7.2所示。图7.2 颜色对话框第9页/共83页7.1.4 颜色和颜色对话框
12、CColorDialog类具有下列的构造函数:CColorDialog(COLORREF clrInit=0,DWORD dwFlags=0,CWnd*pParentWnd=NULL);其中,clrInit用来指定选择的默认颜色值,若此值没指定,则为RGB(0,0,0)(黑色)。pParentWnd用来指定对话框的父窗口指针。dwFlags用来表示定制对话框外观和功能的系列标志参数。它可以是下列值之一或”|”组合:CC_ANYCOLOR 在基本颜色单元中列出所有可得到的颜色 CC_FULLOPEN 显示所有的颜色对话框界面。若此标志没有被设定,则用户单击“规定自定义颜色”按钮才能显示出定制颜色
13、的界面 CC_PREVENTFULLOPEN 禁用“规定自定义颜色”按钮 CC_SHOWHELP 在对话框中显示“帮助”按钮 CC_SOLIDCOLOR 在基本颜色单元中只列出所得到的纯色当对话框“OK”退出(即DoModal返回 IDOK)时,可调用下列成员获得相应的颜色。COLORREF GetColor()const;/返回用户选择的颜色。void SetCurrentColor(COLORREF clr);/强制使用clr作为当前选择的颜色 static COLORREF*GetSavedCustomColors();/返回用户自己定义颜色第10页/共83页7.1.5 图形设备接口Wi
14、ndows为设备环境提供了各种各样的绘图工具,例如用于画线的“画笔”、填充区域的“画刷”以及用于绘制文本的“字体”。MFC封装了这些工具,并提供相应的类来作为应用程序的图形设备接口GDI,这些类有一个共同的抽象基类CGdiObject,具体如表7.3所示。表7.3 MFC的GDI类第11页/共83页7.1.5 图形设备接口1.使用GDI对象在选择GDI对象进行绘图时,往往遵循着下列的步骤:(1)在堆栈中定义一个GDI对象(如CPen、CBrush对象),然后用相应的函数(如CreatePen、CreateSolidBrush)创建此GDI对象。但要注意:有些GDI派生类的构造函数允许用户提供足
15、够的信息,从而一步即可完成对象的创建任务,这些类有CPen、CBrush。(2)将构造的GDI对象选入当前设备环境中,但不要忘记将原来的GDI对象保存起来。(3)绘图结束后,恢复当前设备环境中原来的GDI对象。(4)由于GDI对象是在堆栈中创建中,当程序结束后,会自动删除程序创建的GDI对象。具体操作可像下面的代码过程:void CMyView:OnDraw(CDC*pDC)CPen penBlack;/定义一个画笔变量penBlack.CreatePen(PS_SOLID,2,RGB(0,0,0);/创建画笔/将此画笔选入当前设备环境并保存原来的画笔CPen*pOldPen=pDC-Sele
16、ctObject(&penBlack);/用此画笔绘图pDC-MoveTo(.);pDC-LineTo(.);/其他绘图函数pDC-SelectObject(pOldPen);/恢复设备环境中原来的画笔第12页/共83页7.1.5 图形设备接口2.库存的GDI对象除了自定义的GDI对象外,Windows还包含了一些预定义的库存GDI对象。由于它们是Windows系统的一部分,因此用户用不着删除它们。CDC的成员函数SelectStockObject可以把一个库存对象选入当前设备环境中,并返回原先被选中的对象指针,同时使原先被选中的对象从设备环境中分离出来。如下面的代码:void CEx_SDI
17、View:OnDraw(CDC*pDC)CPen newPen(PS_SOLID,2,RGB(0,0,0)pDC-SelectObject(&newPen);pDC-MoveTo(.);pDC-LineTo(.);/其他绘图函数 pDC-SelectStockObject(BLACK_PEN);/newPen被分离出来第13页/共83页2.库存的GDI对象函数SelectStockObject可选用的库存GDI对象类型可以是下列值之一:BLACK_BRUSH 黑色画刷DKGRAY_BRUSH 深灰色画刷GRAY_BRUSH 灰色画刷HOLLOW_BRUSH 中空画刷LTGRAY_BRUSH 浅
18、灰色画刷NULL_BRUSH 空画刷WHITE_BRUSH 白色画刷BLACK_PEN 黑色画笔NULL_PEN 空画笔WHITE_PEN 白色画笔DEVICE_DEFAULT_FONT 设备默认字体SYSTEM_FONT 系统字体第14页/共83页7.2 简单图形绘制图形的绘制通常需要先创建画笔和画刷,然后调用相应的绘图函数。7.2.1 画笔画笔是Windows应用程序中用来绘制各种直线和曲线的一种图形工具,它可分为修饰画笔和几何画笔两种类型。在这两种类型中,几何画笔的定义最复杂,它不但有修饰画笔的属性,而且还跟画刷的样式、阴影线类型有关,通常用在对绘图有较高要求的场合。而修饰画笔只有简单的
19、几种属性,通常用在简单的直线和曲线等场合。第15页/共83页7.2.1 画笔表7.4 修饰画笔的风格第16页/共83页7.2.1 画笔创建一个修饰画笔,可以使用CPen类的CreatePen函数,其原型如下:BOOL CreatePen(int nPenStyle,int nWidth,COLORREF crColor);其中,参数nPenStyle、nWidth、crColor分别用来指定画笔的风格、宽度和颜色。此外,还有一个CreatePenIndirect函数也是用来创建画笔对象,它的作用与CreatePen函数是完全一样的,只是画笔的三个属性不是直接出现在函数参数中,而是通过一个LOG
20、PEN结构间接地给出。BOOL CreatePenIndirect(LPLOGPEN lpLogPen);此函数用由LOGPEN结构指针指定的相关参数创建画笔,LOGPEN结构如下:typedef struct tagLOGPEN /*lgpn*/UINT lopnStyle;/画笔风格,同上 POINT lopnWidth;/POINT结构的y不起作用,而用x表示画笔宽度 COLORREF lopnColor;/画笔颜色 LOGPEN;第17页/共83页7.2.2 画刷画刷的属性通常包括填充色、填充图案和填充样式三种。画刷的填充色和画笔颜色一样,都是使用COLORREF颜色类型,画刷的填充图
21、案通常是用户定义的8 8位图,而填充样式往往是CDC内部定义的一些特性,它们都是以HS_为前缀的标识,如图7.3所示:HS_BDIAGONALHS_CROSSHS_DIAGCROSSHS_FDIAGONAL HS_HORIZONTAL HS_VERTICAL图7.3 画刷的填充样式第18页/共83页7.2.2 画刷CBrush类根据画刷属性提供了相应的创建函数,例如创建填充色画刷和填充样式画刷的函数为CreateSolidBrush和CreateHatchBrush,它们的原型如下:BOOL CreateSolidBrush(COLORREF crColor);/创建填充色画刷BOOL Cre
22、ateHatchBrush(int nIndex,COLORREF crColor);/创建填充样式画刷其中,nIndex用来指定画刷的内部填充样式,而crColor表示画刷的填充色。与画笔相类似,也有一个LOGBRUSH 逻辑结构用于画刷属性的定义,并通过 CBrush的成员函数CreateBrushIndirect来创建,其原型如下:BOOL CreateBrushIndirect(const LOGBRUSH*lpLogBrush);其中,LOGBRUSH 逻辑结构如下定义:typedef struct tagLOGBRUSH /lb UINT lbStyle;/风格 COLORREF
23、lbColor;/填充色 LONG lbHatch;/填充样式 LOGBRUSH;第19页/共83页7.2.3 图形绘制1.画点、线(1)画点是最基本的绘图操作之一,它是通过调用CDC:SetPixel或CDC:SetPixelV函数来实现的。这两个函数都是用来在指定的坐标上设置指定的颜色,只不过SetPixelV函数不需要返回实际像素点的RGB值;正是因为这一点,函数SetPixelV要比SetPixel快得多。COLORREF SetPixel(int x,int y,COLORREF crColor);COLORREF SetPixel(POINT point,COLORREF crCo
24、lor);BOOL SetPixelV(int x,int y,COLORREF crColor);BOOL SetPixelV(POINT point,COLORREF crColor);实际显示像素的颜色未必等同于crColor所指定的颜色值,因为有时受设备限制,不能显示crColor所指定的颜色值,而只能取其近似值。与上述函数相对应的GetPixel函数是用来获取指定点的颜色。COLORREF GetPixel(int x,int y)const;COLORREF GetPixel(POINT point)const;第20页/共83页1.画点、线(2)画线也是特别常用的绘图操作之一。C
25、DC的LineTo和MoveTo函数就是用来实现画线功能的两个函数,通过这两个函数的配合使用,可完成任何直线和折线的绘制操作。这个当前位置还可用函数CDC:GetCurrentPosition来获得,其原型如下:CPoint GetCurrentPosition()const;LineTo函数正是经当前位置所在点为直线起始点,另指定直线终点,画出一段直线的。其原型如下:BOOL LineTo(int x,int y);BOOL LineTo(POINT point);第21页/共83页7.2.3 图形绘制2.折线除了LineTo函数可用来画线之外,CDC中还提供了一系列用于画各种折线的函数。它
26、们主要是Polyline、PolyPolyline和PolylineTo。这三个函数中,Polyline和PolyPolyline既不使用当前位置,也不更新当前位置;而PolylineTo总是把当前位置作为起始点,并且在折线画完之后,还把折线终点所在位置设为新的当前位置。BOOL Polyline(LPPOINT lpPoints,int nCount);BOOL PolylineTo(const POINT*lpPoints,int nCount);这两个函数用来画一系列连续的折线。参数lpPoints是POINT或CPoint的顶点数组;nCount表示数组中顶点的个数,它至少为2。BOO
27、L PolyPolyline(const POINT*lpPoints,const DWORD*lpPolyPoints,int nCount);此函数可用来绘制多条折线。其中lpPoints同前定义,lpPolyPoints表示各条折线所需的顶点数,nCount表示折线的数目。第22页/共83页7.2.3 图形绘制3.矩形和圆角矩形CDC提供的Rectangle和RoundRect函数分别用于矩形和圆角矩形的绘制,它们的原型如下:BOOL Rectangle(int x1,int y1,int x2,int y2);BOOL Rectangle(LPCRECT lpRect);BOOL Ro
28、undRect(int x1,int y1,int x2,int y2,int x3,int y3);BOOL RoundRect(LPCRECT lpRect,POINT point);参数lpRect的成员left,top,right,bottom分别表示x1,y1,x2,y2,point的成员x,y分别表示x3,y3;而x1,y1表示矩形的左上角坐标,x2,y2表示矩形的右上角坐标,x3,y3表示绘制圆角的椭圆大小,如图7.4所示。图7.4 圆角矩形图7.5 多边形填充模式第23页/共83页7.2.3 图形绘制4.设置多边形填充模式多边形填充模式决定了图形填充时寻找填充区域的方法,有两种
29、选择:ALTERNATE和WINDING。ALTERNATE模式是寻找相邻的奇偶边作为填充区域,而WINDING是按顺时针或逆时针进行寻找;一般情况,这两种模式的填充效果是相同的,但对于像五角星这样的图形,填充的结果大不一样,例如下面的代码,其结果如图7.5所示。.POINTpt5=247,10,230,90,290,35,210,30,275,85;CBrushbrush(HS_FDIAGONAL,RGB(255,0,0);CBrush*oldbrush=pDC-SelectObject(&brush);pDC-SetPolyFillMode(ALTERNATE);pDC-Polygon(p
30、t,5);for(int i=0;iSetPolyFillMode(WINDING);pDC-Polygon(pt,5);pDC-SelectObject(oldbrush);brush.DeleteObject();代码中,SetPolyFillMode是CDC类的一个成员函数,用来设置填充模式,它的参数可以是ALTERNATE和WINDING。第24页/共83页7.2.3 图形绘制5.多边形前面已经介绍过折线的画法,而多边形可以说就是由首尾相接的封闭折线所围成的图形。画多边形的函数Polygon原型如下:BOOL Polygon(LPPOINT lpPoints,int nCount);可
31、以看出,Polygon函数的参数形式与Polyline函数是相同的。但也稍有一点小差异。例如,要画一个三角形,使用Polyline函数,顶点数组中就得给出四个顶点(尽管始点和终点重复出现),而用Polygon函数则只需给出三个顶点。与PolyPolyline可画多条折线一样,使用PolyPolygon函数,一次可画出多个多边形,这两个函数的参数形式和含义也一样。BOOL PolyPolygon(LPPOINT lpPoints,LPINT lpPolyCounts,int nCount);第25页/共83页7.2.3 图形绘制6.圆弧和椭圆通过调用CDC的Arc函数可以画一条椭圆弧线或者整个椭
32、圆。这个椭圆的大小是由其外接矩形(本身并不可见)所决定的。Arc函数的原型如下:BOOL Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);BOOL Arc(LPCRECT lpRect,POINT ptStart,POINT ptEnd);这里,x1,y1,x2,y2或lpRect用来指定外接矩形的位置和大小,而椭圆中心与点(x3,y3)或ptStart所构成的射线与椭圆的交点就成为椭圆弧线的起始点,椭圆中心与点(x4,y4)或ptEnd所构成的射线与椭圆的交点就成为椭圆弧线的终点。椭圆上弧线始点到终点的部分是要绘制的椭
33、圆弧,如图7.6所示。图7.6 弧线中心外接矩形弧线(x1,y1)(x2,y2)起点坐标终点坐标第26页/共83页7.2.3 图形绘制7.弦形和扇形CDC类成员函数Chord和Pie是用来绘制弦形(图7.7)和扇形(图7.8),它们具有和Arc一样的参数。BOOL Chord(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);BOOL Chord(LPCRECT lpRect,POINT ptStart,POINT ptEnd);BOOL Pie(int x1,int y1,int x2,int y2,int x3,int y3,
34、int x4,int y4);BOOL Pie(LPCRECT lpRect,POINT ptStart,POINT ptEnd);图7.7 弦形中心外接矩形弦形(x1,y1)(x2,y2)起点坐标终点坐标图7.8 扇形中心外接矩形扇形(x1,y1)(x2,y2)起点坐标终点坐标第27页/共83页7.2.3 图形绘制8.Bzier曲线Bzier曲线是最常见的非规则曲线之一,它的形状不仅便于控制,而且更主要的是它具有几何不变性(即它的形状不随坐标的变换而改变),因此在许多场合往往采用这种曲线。Bzier曲线属于三次曲线,只需给定四个点(第一和第四个点是端点,另两个是控制点),就可唯一确定其形状,
35、如图7.9所示。P1P2P3P4图7.9 Bzier曲线第28页/共83页8.Bzier曲线函数PolyBezier是用来画出一条或多条Bzier曲线的,其函数原型如下:BOOL PolyBezier(const POINT*lpPoints,int nCount);其中lpPoints是曲线端点和控制点所组成的数组,nCount表示lpPoints数组中的点数。如果lpPoints用于画多条Bzier曲线,那么除了第一条曲线要用到四个点之外,后面的曲线只需用三个点,因为后面的曲线总是把前一条曲线的终点作为自己的起始端点。函数PolyBezier不使用也不更新当前位置。如果需要使用当前位置,那
36、么就应该使用PolyBezierTo函数。BOOL PolyBezierTo(const POINT*lpPoints,int nCount);第29页/共83页7.2.3 图形绘制9.绘图示例下面来看一个简单的示例。它是用来表示一个班级某门课程的成绩分布,用一个直方图来反映90五个分数段的人数,它需要绘制五个矩形,相邻矩形的填充样式还要有所区别,并且还需要显示各分数段的人数。其结果如图7.10所示。图7.10 Ex_Draw运行结果第30页/共83页7.2.3 图形绘制例Ex_Draw 课程的成绩分布直方图用MFC AppWizard创建一个默认的单文档应用程序Ex_Draw。为CEx_Dr
37、awView类添加一个成员函数DrawScore,用来根据成绩来绘制直方图,该函数的代码如下:void CEx_DrawView:DrawScore(CDC*pDC,float*fScore,int nNum)/fScore是成绩数组指针,nNum是学生人数int nScoreNum=0,0,0,0,0;/各成绩段的人数的初始值/下面是用来统计各分数段的人数for(int i=0;inNum;i+)int nSeg=(int)(fScorei)/10;/取数的十位上的值if(nSeg 6)nSeg=5;/90分数段nScoreNumnSeg-5+;/各分数段计数int nSegNum=size
38、of(nScoreNum)/sizeof(int);/计算有多少个分数段第31页/共83页 /求分数段上最大的人数int nNumMax=nScoreNum0;for(i=1;inSegNum;i+)if(nNumMax SelectObject(&brush1);/将brush1选入设备环境CPen*oldPen=pDC-SelectObject(&pen);/将pen选入设备环境CRect rcSeg(rc);rcSeg.right=rcSeg.left+nSegWidth;/使每段的矩形宽度等于nSegWidthCString strSeg=90;CRect rcStr;for(i=0;
39、iSelectObject(&brush2);elsepDC-SelectObject(&brush1);rcSeg.top=rcSeg.bottom-nScoreNumi*nSegHeight-2;/计算每段矩形的高度pDC-Rectangle(rcSeg);if(nScoreNumi 0)CString str;str.Format(%d人,nScoreNumi);pDC-DrawText(str,rcSeg,DT_CENTER|DT_VCENTER|DT_SINGLELINE);rcStr=rcSeg;rcStr.top=rcStr.bottom+2;rcStr.bottom+=20;p
40、DC-DrawText(strSegi,rcStr,DT_CENTER|DT_VCENTER|DT_SINGLELINE);/后面还会讲到rcSeg.OffsetRect(nSegWidth,0);/右移矩形pDC-SelectObject(oldBrush);/恢复原来的画刷属性pDC-SelectObject(oldPen);/恢复原来的画笔属性第33页/共83页例Ex_Draw(3)在CEx_DrawView:OnDraw函数中添加下列代码:void CEx_DrawView:OnDraw(CDC*pDC)CEx_DrawDoc*pDoc=GetDocument();ASSERT_VAL
41、ID(pDoc);float fScore=66,82,79,74,86,82,67,60,45,44,77,98,65,90,66,76,66,62,83,84,97,43,67,57,60,60,71,74,60,72,81,69,79,91,69,71,81;DrawScore(pDC,fScore,sizeof(fScore)/sizeof(float);(4)编译并运行,如前图7.10所示。第34页/共83页7.3 字体与文字处理字体是文字显示和打印的外观形式,它包括了文字的字样、风格和尺寸等多方面的属性。适当地选用不同的字体,可以大大地丰富文字的外在表现力。例如,把文字中某些重要的
42、字句用较粗的字体显示,能够体现出突出、强调的意图。第35页/共83页7.3.1 字体和字体对话框1.字体的属性和创建字体的属性有很多,但其主要属性有字样、风格和尺寸三个。字样是字符书写和显示时表现出的特定模式,例如,对于汉字,通常有宋体、楷体、仿宋、黑体、隶书以及幼圆等多种字样。字体风格主要表现为字体的粗细和是否倾斜等特点。字体尺寸是用来指定字符所占区域的大小,通常用字符高度来描述。字体尺寸可以取毫米或英寸作为单位,但为了直观起见,也常常采用一种称为“点”的单位,一点约折合为1/72英寸。第36页/共83页1.字体的属性和创建逻辑字体的具体属性可由LOGFONT结构来描述,这里仅列最常用到的结
43、构成员。typedef struct tagLOGFONT LONG lfHeight;/字体的逻辑高度 LONG lfWidth;/字符的平均逻辑宽度 LONG lfEscapement;/倾角 LONG lfOrientation;/书写方向 LONG lfWeight;/字体的粗细程度 BYTE lfItalic;/斜体标志 BYTE lfUnderline;/下划线标志 BYTE lfStrikeOut;/删除线标志 BYTE lfCharSet;/字符集,汉字必须为GB2312_CHARSET TCHAR lfFaceNameLF_FACESIZE;/字样名称/LOGFONT;第37
44、页/共83页1.字体的属性和创建根据定义的逻辑字体,用户就可以调用CFont类的CreateFontIndirect函数创建文本输出所需要的字体,如下面的代码:LOGFONT lf;/定义逻辑字体的结构变量memset(&lf,0,sizeof(LOGFONT);/将lf中的所有成员置0lf.lfHeight=-13;lf.lfCharSet=GB2312_CHARSET;strcpy(LPSTR)&(lf.lfFaceName),黑体);/用逻辑字体结构创建字体CFontcf;cf.CreateFontIndirect(&lf);/在设备环境中使用字体CFont*oldfont=pDC-Se
45、lectObject(&cf);pDC-TextOut(100,100,Hello);pDC-SelectObject(oldfont);/恢复设备环境原来的属性cf.DeleteObject();/删除字体对象第38页/共83页7.3.1 字体和字体对话框2.使用字体对话框CFontDialog类提供了字体及其文本颜色选择的通用对话框,如图7.11所示。它的构造函数如下:CFontDialog(LPLOGFONT lplfInitial=NULL,DWORD dwFlags=CF_EFFECTS|CF_SCREENFONTS,CDC*pdcPrinter=NULL,CWnd*pParentW
46、nd=NULL);其中,参数lplfInitial是一个LOGFONT结构指针,用来设置对话框最初的字体特性。dwFlags指定选择字体的标志。pdcPrinter用来表示打印设备环境指针。pParentWnd表示对话框的父窗口指针。图7.11 字体对话框第39页/共83页2.使用字体对话框当字体对话框DoModal返回IDOK后,可使用下列的成员函数:void GetCurrentFont(LPLOGFONT lplf);/返回用户选择的LOGFONT字体CString GetFaceName()const;/返回用户选择的字体名称CString GetStyleName()const;/返
47、回用户选择的字体样式名称int GetSize()const;/返回用户选择的字体大小COLORREF GetColor()const;/返回用户选择的文本颜色int GetWeight()const;/返回用户选择的字体粗细程度BOOL IsStrikeOut()const;/判断是否有删除线BOOL IsUnderline()const;/判断是否有下划线BOOL IsBold()const;/判断是否是粗体BOOL IsItalic()const;/判断是否是斜体。第40页/共83页2.使用字体对话框通过字体对话框可以创建一个字体,如下面的代码:LOGFONT lf;CFontcf;me
48、mset(&lf,0,sizeof(LOGFONT);/将lf中的所有成员置0CFontDialog dlg(&lf);if(dlg.DoModal()=IDOK)dlg.GetCurrentFont(&lf);pDC-SetTextColor(dlg.GetColor();cf.CreateFontIndirect(&lf);.第41页/共83页7.3.2 常用文本输出函数文本的最终输出不仅依赖于文本的字体,而且还跟文本的颜色、对齐方式等有很大关系。CDC类提供了四个输出文本的成员函数:TextOut、ExtTextOut、TabbedTextOut和DrawText。对于这四个函数,用户应
49、根据具体情况来选用。例如,如果想要绘制的文本是一个多列的列表形式,那么采用TabbedTextOut函数,启用制表位,可以使绘制出来的文本效果更佳;如果要在一个矩形区域内绘制多行文本,那么采用DrawText函数,会更富于效率;如果文本和图形结合紧密,字符间隔不等,并要求有背景颜色或矩形裁剪特性,那么ExtTextOut函数将是最好的选择。如果没有什么特殊要求,那使用TextOut函数就显得简练了。下面介绍TextOut、TabbedTextOut和DrawText函数。virtual BOOL TextOut(int x,int y,LPCTSTR lpszString,int nCount
50、);BOOL TextOut(int x,int y,const CString&str);第42页/共83页7.3.2 常用文本输出函数virtual CSize TabbedTextOut(int x,int y,LPCTSTR lpszString,int nCount,int nTabPositions,LPINT lpnTabStopPositions,int nTabOrigin);CSize TabbedTextOut(int x,int y,const CString&str,int nTabPositions,LPINT lpnTabStopPositions,int nTa