版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第三讲MFC绘图基础主讲:吕骏
Windows是一个图形操作系统,大多数应用程序都需要在客户区绘制一些图形,如绘制文本、几何图形、位图和光标等。Windows提供了一个称为图形设备接口GDI(GraphicsDeviceInterface)的抽象接口。GDI作为Windows的重要组成部分,它负责管理用户绘图操作时功能的转换。用户通过调用GDI函数与设备打交道,GDI通过不同设备提供的驱动程序将绘图语句转换为对应的绘图指令,避免了直接对硬件进行操作,从而实现所谓的设备无关性。所谓设备无关性,是指操作系统屏蔽了硬件设备的差异,使用户编程时一般无需考虑设备的类型,如不同种类的显示器或打印机。
Windows绘图过程和设备无关性的实现:
GDI处于设备驱动程序的上一层,当程序调用绘图函数时,GDI将绘图命令传送给当前设备的驱动程序,以调用驱动程序提供的接口函数。驱动程序的接口函数将Windows绘图命令转化为设备能够执行的输出命令,实现图形的绘制。不同设备具有不同的驱动程序,设备驱动程序是设备相关的。设备环境DC(DeviceContext)为了实现设备无关性,应用程序的输出不直接面向显示器等物理设备,而是面向一个称之为设备环境DC(DeviceContext)的虚拟逻辑设备。设备环境也称设备描述表或设备上下文,它是由Windows管理的一个数据结构,它保存了绘图操作中一些共同需要设置的信息,如当前的画笔、画刷、字体和位图等图形对象及其属性,以及颜色和背景等影响图形输出的绘图模式。形象地说,一个设备环境提供了一张画布和一些绘画的工具,我们可以使用不同颜色的工具在上面绘制点、线、圆和文本。在Windows中不使用DC无法进行输出,在使用任何GDI绘图函数之前,必须建立一个设备环境。获取设备环境DC的方法:
在程序中不能直接存取DC数据结构,只能通过系统提供的一系列函数或使用设备环境的句柄HDC来间接地获取或设置设备环境结构中的各项属性,如显示器高度和宽度、支持的颜色数及分辨率等。如果采用SDK方法编程,获取DC的方法有两种:在WM_PAINT消息处理函数中通过调用API函数BeginPaint()获取设备环境,在消息处理函数返回前调用API函数EndPaint()释放设备环境。在其他函数中通过调用API函数GetDC()获取设备环境,调用API函数ReleaseDC()释放设备环境。获取设备描述表:方法一该方法适合于处理非WM_PAINT消息用GetDC获取设备描述表句柄用ReleaseDC释放设备描述表句柄这种获取设备描述表的一般方式如下 hdc=GetDC(hwnd);
……
ReleaseDC(hwnd,hdc);9WM_PAINT消息什么时候向窗口过程发送WM_PAINT消息(窗口发生重绘)-“无效”的时候调用UpdateWindow函数刷新窗口窗口的全部或者部分失效的时候窗口从无到有手动刷新窗口调用InvalidateRect函数计算机科学与技术学院张淼10获取设备描述表:方法二该方法只适合于处理WM_PAINT消息用BeginPaint“使无效窗口生效”并“返回设备描述表句柄”用EndPaint释放设备描述表句柄一般处理WM_PAINT的形式如下:CaseWM_PAINT; hdc=BeginPaint(hwnd,&ps);
……
EndPaint(hwnd,&ps); return0;如果采用MFC方法编程,MFC提供了不同类型的DC类,每一个类都封装了DC句柄,并且它们的构造函数自动调用获取DC的API函数,析构函数自动调用释放DC的API函数。因此,在程序中通过声明一个MFC设备环境类的对象就自动获取了一个DC,而当该对象被销毁时就自动释放了获取的DC。MFCAppWizard应用程序向导创建的OnDraw()函数自动支持所获取的DC。MFC的DC类包括CDC、CPaintDC、CClientDC、CWindowDC等,其中CDC类是MFC设备环境类的基类,其它的MFC设备环境类都是CDC的派生类。CDC类既作为其它MFC设备环境类的基类,又可以作为一个一般的设备环境类使用。利用它可以访问设备属性和设置绘图属性。CDC类对GDI的所有绘图函数进行了封装。CPaintDC类是OnPaint()函数使用的设备环境类,它代表一个窗口的绘图画面。如果添加WM_PAINT消息处理函数OnPaint(),就需要使用CPaintDC类来定义一个设备环境对象。CClientDC类代表了客户区设备环境。当在客户区实时绘图时,需要利用CClientDC类定义一个客户区设备环境。CWindowDC类代表了整个程序窗口设备环境,可以在整个窗口区域绘图。CClientDC、CPaintDC和CWindowDC的区别当窗口的某个区域需要重绘时激发窗口重绘消息WM_PAINT,相应消息处理函数CWnd::OnPaint将被调用。CPaintDC一般只用于OnPaint函数中,在处理完窗口重绘后,
CPaintDC对象的析构函数把WM_PAINT消息从消息队列中清除,避免不断地重绘操作。坐标原点(0,0)是客户区的左上角。CClientDC用于特定窗口客户区(窗口中除边框、标题栏、菜单栏、状态栏外的中间部分)的输出,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC,不需要显式释放DC资源。一般用于响应非重绘消息(如键盘和鼠标消息)的绘图操作。坐标原点(0,0)是客户区的左上角。CWindowDC在整个应用程序窗口上画图,而CClientDC和CPaintDC只能在客户区绘制图形;除非要自己绘制窗口边框和按钮,否则一般不用它。坐标原点(0,0)是屏幕的左上角。13MFC中获取DC的方法在如OnDraw等函数中传递一个指向CDC对象的指针如OnDraw(CDC*pDC);使用构造函数构建对象一般不构造CDC对象在CWnd类的OnPaint函数中,定义CPaintDC对象CPaintDCdc(this);在CWnd类的其它函数中,定义CClientDC和CWindowDC的对象CClientDCdc(this);CWindowDCdc(this);OnDraw与OnPaint的区别OnDraw是CView类的成员函数,不响应消息;OnPaint是CWnd类的成员函数,相应WM_PAINT消息。CView默认调用的OnPaint函数如下
voidCView::OnPaint()
{
CPaintDCdc(this);
OnPrepareDC(&dc);
OnDraw(&dc);//调用了OnDraw
}可见OnPaint函数也调用了CView::OnDraw函数。因而一般在OnDraw函数内添加绘图代码,完成绘图任务15
GDI坐标系和映射模式Windows坐标系分为逻辑坐标系和设备坐标系两种,GDI支持这两种坐标系。一般而言,GDI的文本和图形输出函数使用逻辑坐标,而在客户区移动或按下鼠标的鼠标位置是采用设备坐标。逻辑坐标系是面向DC的坐标系,这种坐标不考虑具体的设备类型,在绘图时,Windows会根据当前设置的映射模式将逻辑坐标转换为设备坐标。设备坐标系是面向物理设备的坐标系,这种坐标以像素或设备所能表示的最小长度单位为单位,X轴方向向右,Y轴方向向下。设备坐标系的原点位置(0,0)不限定在设备显示区域的左上角。设备坐标系统设备坐标系统x轴自左至右,y轴从上到下,坐标原点在屏幕左上角[0,0]XYO17设备坐标系分为屏幕坐标系、窗口坐标系和客户区坐标系三种相互独立的坐标系。屏幕坐标系以屏幕左上角为原点,一些与整个屏幕有关的函数均采用屏幕坐标,如GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()。弹出式菜单使用的也是屏幕坐标。窗口坐标系以窗口左上角为坐标原点,它包括窗口标题栏、菜单栏和工具栏等范围。客户区坐标系以窗口客户区左上角为原点,主要用于客户区的绘图输出和窗口消息的处理。鼠标消息的坐标参数使用客户区坐标,CDC类绘图成员函数使用与客户区坐标对应的逻辑坐标。坐标之间的相互转换编程时,有时需要根据当前的具体情况进行三种设备坐标之间或与逻辑坐标的相互转换。MFC提供了两个函数CWnd::ScreenToClient()和CWnd::ClientToScreen()用于屏幕坐标与客户区坐标的相互转换。MFC提供了两个函数CDC::DPtoLP()和CDC::LPtoDP()用于设备坐标与逻辑坐标之间的相互转换。生成设备环境,就可以开始绘制不同形状的几何图形,GDI提供了绘制基本图形的成员函数,这些函数封装在MFC的CDC类中。CDC类提供的绘图函数包括点、直线、曲线、矩形、椭圆、弧、扇形、弦形和多边形等供用户使用。如果进行复杂绘图的话,就需要通过算法来组织这些基本绘图函数来完成绘图。绘图函数使用的坐标都是逻辑坐标。
绘制基本图形
函
数功
能SetPixel用指定的颜色在指定的坐标画一个点MoveTo移动当前位置到指定的坐标,函数返回以前位置的坐标。LineTo从当前位置到指定位置画一条直线Polyline从当前位置开始,根据函数参数绘制多条折线。PolyBezier根据两个端点和两个控制点绘制贝济埃(Bezier)曲线。Rectangle根据指定的左上角和右下角坐标绘制一个矩形RoundRect绘制一个圆角矩形。Ellipse根据指定的矩形绘制一个内切椭圆Arc根据指定的矩形绘制内切椭圆上的一段弧边ArcTo该函数功能与Arc函数相同,不同之处在于画弧成功后Pie绘制扇形Chord绘制弦形,弦形是一条椭圆弧和其对应的弦所组成的封闭图形。Polygon根据两个或两个以上顶点绘制一个多边形DrawIcon在指定位置画一个图标,如果成功函数返回非0,否则返回0。画线LineTo函数用于绘制一条从当前绘图位置到指定坐标点的直线段,其函数声明如下:BOOLLineTo(intx,inty);BOOLLineTo(POINTpoint);参数x和y,及参数point指定了坐标点,默认情况下从(0,0)开始画
利用MFCAppWizard建立一个SDI应用程序,在OnDraw()函数中添加如下程序代码:
pDC->LineTo(10,10);POINTp1;p1.x=100;p1.y=100;//使用POINT结构pDC->LineTo(p1);CPointp2;p2.x=200;p2.y=100;//使用CPoint类pDC->LineTo(p2);移动画笔MoveTo函数用于将当前绘图位置移到指定的坐标点处,函数声明如下:CPointMoveTo(intx,inty);CPointMoveTo(POINTpoint);参数x和y,及参数point指定了新的当前绘图位置坐标。返回值是CPoint对象实例,它包含了新的当前绘图位置坐标。Rectangle函数用于绘制矩形,其函数声明如下:BOOLRectangle(intx1,inty1,intx2,inty2);BOOLRectangle(LPCRECTlpRect);其中第一个函数参数给出了两组点坐标,第一组为矩形的左上角点坐标,第二组为矩形的右下角点坐标。第二个函数使用了指向矩形区域结构的指针作为参数,也可以使用CRect类。如果绘图成功,函数返回TRUE,否则返回FALSE。修改OnDraw函数,输入如下代码: pDC->Rectangle(50,50,200,80); CRectr; r.left=100;r.right=200; r.top=100;r.bottom=200; pDC->Rectangle(r);(left,top是左上角坐标,right,bottom是右下角坐标)Ellipse函数用于绘制椭圆或者圆,其函数声明如下:BOOLEllipse(intx1,inty1,intx2,inty2);BOOLEllipse(LPCRECTlpRect);其中,第一个函数的参数x1和y1指定了要绘制的椭圆或者圆的外接矩形的左上角点坐标,参数x2和y2指定了要绘制的椭圆或者圆的外接矩形的右下角点坐标。第二个函数的参数使用了矩形区域结构来存放外接矩形的左上角和右下角坐标。如果绘图成功,函数返回TRUE,否则返回FALSE。修改OnDraw函数,输入如下代码:pDC->Ellipse(50,50,200,80);Arc函数用于绘制一个椭圆形的弧线,它是一个指定的矩形的内切椭圆的一段。所绘制弧线的实际起点是该内切椭圆与一条直线的交点,而该直线是从椭圆中心到指定点的连线。弧线的实际终点也是如此。如图所示:函数声明如下:BOOLArc(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);函数参数给出了四对坐标:第一对坐标是要绘制的圆弧所在椭圆的外接矩形的左上角坐标;第二对坐标是要绘制的圆弧所在椭圆的外接矩形的右下角坐标;第三对坐标指定了圆弧的起点;第四对坐标指定了圆弧的终点。在画圆弧时,默认的圆弧方向是逆时针,即圆弧是按逆时针方向从起点到终点的。修改OnDraw函数,输入如下代码: pDC->Arc(100,100,300,300,100,150,250,150);
Pie函数用于绘制扇形,它是由椭圆弧与其起始点和终止点所对应的椭圆的半径所围成的图形,其函数声明如下:BOOLPie(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);其参数含义与Arc函数相同,差别在于Arc函数只绘制了椭圆弧,而Pie函数将椭圆弧所确定的扇形绘制出来。如果绘图成功,函数返回TRUE,否则返回FALSE。修改OnDraw函数,输入如下代码:pDC->Pie(100,100,300,300,100,150,250,150);Polygon函数用于绘制一个封闭的多边形,其函数声明如下:BOOLPolygon(LPPOINTlpPoints,intnCount);参数lpPoints存放的是多边形的顶点坐标,nCount是多边形的顶点数目,该参数必须大于2。如果绘图成功,函数返回TRUE,否则返回FALSE。修改OnDraw函数,输入如下代码:POINTp[5];p[0].x=10;p[0].y=10;p[1].x=100;p[1].y=100;p[2].x=200;p[2].y=100;p[3].x=200;p[3].y=200;p[4].x=100;p[4].y=50;pDC->Polygon(p,5);在默认状态下,当用户创建一个设备环境并在其中绘图时,系统使用设备环境缺省的绘图工具及其属性。如果要使用不同风格和颜色的绘图工具进行绘图,用户必须重新为设备环境设置自定义的画笔和画刷等绘图工具。
画笔和画刷
绘图工具类主要包括画笔CPen、画刷Cbrush、字体CFont、位图Bitmap和调色板Cpalette等。类继承关系如图CObjectCPen类:GDI画笔,用于画线。默认的画笔用于绘制与一个像素等宽的黑色实线。CBrush类:GDI画刷,用来填充一个封闭图形对象(如矩形、圆形)的内部区域,默认的画刷颜色是白色。CFont类:GDI字体,用来绘制文本,可设置文字的大小、是否加粗、是否斜体、是否加下划线等。CBitmap类:GDI位图,用于填充区域。CPalette类:GDI调色板,包含系统可用的色彩信息,是应用程序和彩色输出设备环境(如显示器)的接口。CRgn类:GDI区域,用于设备环境(通常是窗口)内的区域操作,通常和CDC类中与裁剪(clipping)有关的成员函数配合使用。39CDC类提供了成员函数SelectObject()选择用户自己创建的GDI对象,该函数有多种重载形式,可以选择用户已定制好的画笔、画刷、字体和位图等不同类型的GDI对象。CPen*SelectObject(CPen*pPen);CBrush*SelectObject(CBrush*pBrush);virtualCFont*SelectObject(CFont*pFont);CBitmap*SelectObject(CBitmap*pBitmap);函数参数是一个指向用户已定制好的GDI对象的指针,选择操作成功函数将返回以前GDI对象的指针,否则返回NULL。选择一个GDI对象:
颜色的设置Windows用COLORREF类型的数据存放颜色,它是一个32位整数。任何一种颜色都是由红、绿、蓝三种基本颜色组成,COLORREF类型数据的低位字节存放红色强度值,第2个字节存放绿色强度值,第3个字节存放蓝色强度值,高位字节为0,每一种颜色分量的取值范围为0到255。直接设置COLORREF数据不太方便,Windows提供了RGB宏用于设置颜色,将其中的红、绿、蓝分量值转换为COLORREF类型的颜色数据:RGB(byRed,byGreen,byBlue)其中参数byRed、byGreen和byBlue分别表示红、绿、蓝分量值(范围0到255)。RGB宏的使用:
很多涉及到颜色的GDI函数都需要使用COLORREF类型的参数,如设置背景色的成员函数CDC::SetBkColor()、设置文本颜色的成员函数CDC::SetTextColor()。例如:COLORREFrgbBkClr=RGB(192,192,192); //定义灰色
pDC->SetBkCorlor(rgbBkClr)//背景色为灰色pDC->SetTextColor(RGB(0,0,255)); //文本颜色为兰色标准彩色的RGB值
颜色RGB分量值颜色RGB分量值浅红255,0,0深红128,0,0浅绿0,255,0深绿0,128,0浅蓝0,0,255深蓝0,0,128浅黄255,255,0深黄128,128,0浅青0,255,255深青0,128,128紫色255,0,255灰色192,192,192白色255,255,255黑色0,0,0
使用画笔当用户创建一个用于绘图的设备环境时,该设备环境自动提供了一个宽度为一个像素单位、风格为实黑线(BLACK_PEN)的缺省画笔。如果要在设备环境使用自己的画笔绘图,首先需要创建一个指定风格的画笔,然后将创建的画笔选入设备环境,最后,在使用该画笔绘图结束后需要释放该画笔。
1.创建画笔创建画笔最简单的方法是调用CPen类的一个带参数的构造函数来构造一个CPen类画笔对象,以下代码创建了一个红色虚线画笔:CPenPenNew(PS_DASH,1,RGB(255,0,0));创建画笔的第二种方法是首先构造一个没有初始化的CPen类画笔对象,然后调用成员函数CPen::CreatePen()创建定制的画笔工具:CPenPenNew;PenNew.CreatePen(PS_DASH,1,RGB(255,0,0));函数CreatePen()的参数类型与带参数的CPen类构造函数完全一样。当画笔对象的声明与创建不在同一个地方时(如需要多次改变画笔)只有采用这种方法。画笔式样(PenStyle)样式说明样式说明PS_SOLID实线PS_DASHDOTDOT双点划线PS_DOT点线PS_NULL空的边框PS_DASH虚线PS_INSIDEFRAME边框实线PS_DASHDOT点划线
创建画笔后必须调用成员函数CDC::SelectObject()将创建的画笔选入当前设备环境。如果选择成功,函数SelectObject()将返回以前画笔对象的指针。选择新的画笔时应该保存以前的画笔对象,如下代码所示:CPen*pPenOldpPenOld=pDC>SelectObject(&PenNew);2.选择创建的画笔
创建和选择画笔工具后,应用程序就可以使用该画笔绘图。当绘图完成后,应该通过调用成员函数CDC::SelectObject()恢复设备环境以前的画笔工具,并通过调用成员函数CGdiObject::DeleteObject()释放GDI对象所占的内存资源,如下代码所示:pDC->SelectObject(pPenOld); //恢复设备环境DC中原来的画笔PenNew.DeleteObject(); //删除底层的GDI对象3.还原画笔
例
编写一个SDI应用程序,绘制不同风格、宽度和颜色的直线。
在OnDraw()函数中添加如下所示的代码:CPen*pPenOld,PenNew;intnPenStyle[]={ PS_SOLID,//实线
PS_DOT,//点线
PS_DASH,//虚线
PS_DASHDOT,//点划线
PS_DASHDOTDOT,//双点划线
PS_NULL, //空的边框
PS_INSIDEFRAME,//边框实线};LPTSTRstrStyle[]={_T("Solid"),_T("Dot"),_T("Dash"),_T("DashDot"),_T("DashDotDot"),_T("Null"),_T("InsideFrame")};pDC->TextOut(60,10,_T("用不同样式的画笔绘图"));
for(inti=0;i<7;i++)//用不同样式画笔绘图{
if(PenNew.CreatePen(nPenStyle[i],1,RGB(0,0,0)))//创建画笔{pPenOld=pDC->SelectObject(&PenNew); //选择画笔
pDC->TextOut(10,30+20*i,strStyle[i]); pDC->MoveTo(100,40+20*i); pDC->LineTo(200,40+20*i);pDC->SelectObject(pPenOld); //恢复原来的画笔PenNew.DeleteObject();//删除底层的GDI对象}else
{ MessageBox(_T("不能创建画笔!"));}}当创建一个设备环境时,该设备环境自动提供了一个填充色为白色(WHITE_BRUSH)的缺省画刷。与画笔一样,也可以利用MFC画刷类CBrush创建自己的画刷,用于填充图形的绘制。画刷有三种基本类型:纯色画刷、阴影画刷和图案画刷,CBrush类提供了多个不同重载形式的构造函数。以下创建三种不同类型的画刷:CBrushbrush1(RGB(255,0,0));//创建纯色画刷CBrushbrush2(HS_DIAGCROSS,RGB(0,255,0)); //创建阴影画刷CBrushbrush3(&bmp); //创建图案画刷使用画刷创建画刷也可先构造一个没有初始化的CBrush类画刷对象,然后调用CBrush类的初始化成员函数创建定制的画刷工具。CBrush类提供的常用创建函数有:CreateSolidBrush()用指定的颜色创建一个纯色画刷;CreateHatchBrush()用指定的阴影样式和颜色创建一个阴影画刷;CreatePatternBrush()用位图创建一个图案画刷;CreateSysColorBrush()用系统默认颜色创建一个指定阴影样式的画刷。阴影画刷使用预定义的六种阴影样式进行绘图。表2.3列出了六种阴影样式。修改OnDraw函数,输入如下代码:CBrushbrush(HS_CROSS,RGB(255,0,0));//构造一个十字交叉线的阴影线画刷,前景色为红色CPenpen(PS_SOLID,2,RGB(0,0,255));//构造一个宽度为2,颜色为蓝色的实线画笔pDC->SelectObject(&pen);pDC->SelectObject(&brush);//选择画笔和画刷pDC->Rectangle(200,200,300,300);pen.DeleteObject();brush.DeleteObject();//删除画笔和画刷对象很多Windows应用程序都需要显示文本,并且,文本还是一些应用程序的主要处理对象,如MSWord字处理软件。文本与字体密切相关,输出文本时选择不同类型的字体在很大程度上影响程序的界面风格,合适的字体可以增强程序的感染力。因此,对软件用户来说,文本输出也是很重要的。Windows为文本的显示提供了多种物理字体支持,而在程序中我们可以创建不同风格的逻辑字体来输出文本。
文本与字体
以图形方式进行文本的输出是Windows操作系统一个特性,文本输出实际上是按照指定的字体样式将文本中的每个字符绘制出来。编程时最常用的文本输出函数是TextOut()函数,该函数只能输出单行文本。要绘制多行文本可以调用DrawText()函数,另一个函数ExtTextOut()可以用一个矩形框对输出文本串进行裁剪。绘制文本通过API函数TextOut执行文本输出操作。BOOLTextOut(__in
HDChdc,__in
intnXStart,__in
intnYStart,__in
LPCTSTRlpString,__in
intcbString);参数hdc为设备上下文的句柄;参数nXStart为起始点x坐标;参数nYStart为起始点y坐标;参数lpString为要输出的文本字符串;参数cbString为字符串中要输出的字符的数量。使用设备上下文类CDC的成员函数TextOut来输出,CDC::TextOut函数的两种重载形式virtualBOOLTextOut(intx,inty,LPCTSTRlpszString,intnCount);
BOOLTextOut(intx,inty,constCString&str);参数x指定文本起始点的x坐标;参数y指定文本起始点的y坐标;参数lpszString为要输出的文本字符串;参数nCount指定字符串中的字节个数;参数str为包含要输出的字符的CString对象。(2)设置文本颜色在默认情况下,Windows绘制黑色文本。可以通过SetTextColor()函数改变文本的颜色。例如:pDC->SetTextColor(RGB(255,0,0));//设置文本颜色为红色可以通过GetTextColor()函数检索到当前文本的颜色,例如COLORREFcolor=pDC->GetTextColor();SetBkColor()和GetBkColor()函数用于设置背景颜色和获取当前的背景颜色。(3)设置字符间距
SetTextCharacterExtra()函数用来设置文本字符的间距,GetTextCharacterExtra()用来获得当前文本字符的间距,函数说明如下:
pDC->SetTextCharacterExtra(space);intspace=pDC->GetTextCharacterExtra();
其中,space表示在文本字符之间使用的额外空间的像素数。SetTextAlign()函数用于设置显示文本的对齐方式,函数说明如下:
pDC->SetTextAlign(alignment);
其中,alignment参数取值:TA_LEFT、TA_CENTER和TA_RIGHT,分别表示左对齐、居中方法和右对齐。Alignment参数取值:TA_TOP、TA_BOTTOM和TA_BASELINE分别表示文本在垂直方向的对齐方式,上对齐、下对齐和字符的基线对齐。输出文本时,默认情况下使用系统提供的缺省字体,如果需要可以改变显示文本的字体。与画笔和画刷一样,字体也是一种GDI对象,MFC类CFont对GDI字体对象进行了封装,我们一般利用CFont类创建自己的字体(GDI对象),然后把创建的字体选入设备环境,以用于在设备环境中绘制文本。
Windows支持光栅字体、矢量字体和TrueType三种字体。光栅字体即点阵字体,这种字体需要为每一种大小的字体创建独立的字体文件。矢量字体以一系列线段存储字符。TrueType字体是与设备无关的字体,字符以轮廓的形式存储,包括线段和曲线。
字体概述
TrueType字体正成为真正的主流,这种字体能够以一种非常出色的字体技术绘制文本。TrueType字体能够缩放为任何大小的字体,而不会降低图形的质量。Windows中提供的TrueType字体主要有Arial、Courier、Symbol、TimeNewRoman等,可以通过Windows“控制面板|字体”浏览系统已安装的字体。CFont类成员函数CFont()构造一个CFont对象。此对象在使用之前应该先使用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect初始化。BOOLCreateFont(intnHeight,intnWidth,intnEscapement,intnOrientation,intnWeight,BYTEbItalic,BYTEbUnderline,BYTEcStrikeOut,BYTEnCharSet,BYTEnOutPrecision,BYTEnClipPrecision,BYTEnQuality,
BYTEnPitchAndFamily,LPCTSTRlpszFacename)通过指定的一些特征初始化CFont对象。各参数的意义及取值参考MSDN。BOOLCreateFontIndirect(constLOGFONT*lpLogFont)通过一个LOGFONT结构体变量给出的特征来初始化CFont对象。参数lpLogFont是指向LOGFONT结构体变量的指针,此LOGFONT结构体变定义了逻辑字体的特征。LOGFONT结构体的定义参见字体对话框或CSDN。BOOLCreatePointFont(intnPointSize,LPCTSTRlpszFaceName,CDC*pDC=NULL)此函数提供了一种由指定字样和点数创建字体的简单方式。BOOLCreatePointFontIndirect(constLOGFONT*lpLogFont,CDC*pDC=NULL)此函数是通过指定的字样和点数创建字体的间接方式。例:CClientDCdc(this);CFontfntZdy,*pfntOld;fntZdy.CreatePointFont(200,_T("Arial“),&dc);pfntOld=dc.SelectObject(&fntZdy);//选入设备环境dc.TextOut(100,100,_T("Hello!Thisis20PtArialFont."));dc.SelectObject(pfntOld); //恢复原来字体fntZdy.DeleteObject();//删除自定义字体
例:CFontfont;LOGFONTLogFnt;memset(&LogFnt,0,sizeof(LOGFONT));//清零结构LogFontLogFnt.lfHeight=22;//字体高度为22像素LogFnt.lfItalic=true;//斜体LogFnt.lfWeight=FW_BOLD;//粗黑wcscpy_s(LogFnt.lfFaceName,_T("Courier“));//匹配字体为Courierfont.CreateFontIndirect(&LogFnt);//创建字体CClientDCdc(this);CFont*def_font=dc.SelectObject(&font);//选入设备环境dc.TextOut(100,130, _T("Hello!Thisis22-pixel-heightCourierFont."));dc.SelectObject(def_font);font.DeleteObject();Windows预定义了一些简单风格的GDI对象,用户使用这些GDI对象时,无需自己创建它们,可以直接将它们选入当前的设备环境,这些GDI对象称作为堆(Stock)对象。堆对象包括堆画笔、堆画刷和堆字体等。
使用GDI堆对象通过调用成员函数CDC::SelectStockObject()可以选择一个堆对象绘图工具,以下代码将堆画笔和堆画刷作为当前的绘图工具: pPenOld=(CPen*)pDC->SelectStockObject(NULL_PEN); //使用堆画笔对象 pBrhOld=(CBrush*)pDC->SelectStockObject(LTGRAY _BRUSH); //使用堆画刷对象堆画笔、画刷的样式及说明
样式说明样式说明BLACK_PEN黑色画笔WHITE_PEN白色画笔NULL_PEN空画笔BLACK_BRUSH黑色画刷WHITE_BRUSH白色画刷NULL_BRUSH空画刷GRAY_BRUSH灰色画刷DKGRAY_BRUSH深灰色画刷LTGRAY_BRUSH浅灰色画刷HOLLOW_BRUSH虚画刷
利用MFCAppWizard向导创建一个SDI应用程序UseStock,利用ClassWizard为类CUseStockView添加WM_PAINT消息处理函数OnPaint():CPen*pPenOld,PenNew;CBrush*pBrhOld,BrhNew;pPenOld=(CPen*)dc.SelectStockObject(BLACK_PEN); //使用堆画笔对象pBrhOld=(CBrush*)dc.SelectStockObject(GRAY_BRUSH); //使用堆画刷对象例
编写一个SDI应用程序,使用堆画笔和堆画刷绘制图形。
dc.Rectangle(100,100,300,300);PenNew.CreateStockObject(NULL_PEN);//NULL_PEN用于绘制无边界的填充图形dc.SelectObject(&PenNew);BrhNew.CreateStockObject(LTGRAY_BRUSH);dc.SelectObject(&BrhNew);dc.Ellipse(400,100,600,200);dc.SelectObject(pPenOld);//恢复系统默认的GDI对象dc.SelectObject(pBrhOld);dc.Ellipse(400,210,600,310);
鼠标橡皮筋技术画圆就是采用圆心和圆周上任一点画圆技术(简称C+P方法),首先用鼠标左击选择圆心位置,然后移动鼠标,圆随鼠标移动而扩大或缩小,当再次单击鼠标左键时,确定圆周上的一点,从而画出相应的圆。直线、矩形等基本图形都可以采用橡皮筋技术。
采用鼠标橡皮筋技术画圆第一步:建立MouseSpring工程文件;第二步:向视图类中添加自定义的成员变量proctected:CPointm_bO;//圆心
CPointm_bR;//圆上的点
intm_ist;//圆心与圆周上点的区别,m_ist=0,表示鼠标左击点为圆心,m_ist=1,表示鼠标左击点为圆周上的点第三步:向视图类中添加自定义的成员函数原型:
public:voidDrawCircle(CDC*pDC,CPointcenp,CPointardp);intComputeRadius(CPointcenp,CPointardp);分别为两个成员函数DrawCircle()和ComputeRadius()添加程序代码,程序如下:voidCMouseSpringView::DrawCircle(CDC*pDC,CPointcenp,CPointardp){intradius=ComputeRadius(cenp,ardp);
//由圆心确定所画圆的外切区域
CRectrc(cenp.x-radius,cenp.y-radius,cenp.x+radius,cenp.y+radius);pDC->Ellipse(rc);//画出一个整圆}第四步:添加成员函数的程序代码。intCMouseSpringView::ComputeRadius(CPointcenp,CPointardp){floatdx=cenp.x-ardp.x;floatdy=cenp.y-ardp.y;
//sqrt()函数的调用,在头文件中加入#include<cmath>return(int)sqrt(dx*dx+dy*dy);}第五步:在视图类CPP文件的构造函数中初始化成员变量
视图类的构造函数名与该视图类的名字相同。在视图类中选择构造函数,如:CMouseSpringView(),用鼠标左键双击,输入下面程序代码:CMouseSpringView::CMouseSpringView(){//TODO:addconstructioncodeherem_bO.x=0;m_bO.y=0;//圆心
m_bR.x=0;m_bR.y=0;//圆上的点
m_ist=0;//圆心与圆上的点区别}第六步:在视图类的OnDraw()函数中加入下列代码,实现视图绘图。
pDC->SelectStockObject(NULL_BRUSH); DrawCircle(pDC,m_bO,m_bR);//调用自定义的成员函数画圆第七步:向视图类中添加两个鼠标消息响应函数,并输入鼠标处理程序代码。一个是OnLButtonDown()函数程序如下: CDC*pDC=GetDC();pDC->SelectStockObject(NULL_BRUSH); if(!m_ist)//绘制圆
{m_bO=m_bR=point;
//纪录第一次单击鼠标位置,定圆心
m_ist++; }
else {m_bR=point;//记录第二次单击鼠标的位置,定圆周上的点
m_ist--;//为新绘图作准备
DrawCircle(pDC,m_bO,m_bR);//绘制新圆
} ReleaseDC(pDC);//释放设备环境另一个是OnMouseMove()函数,程序如下 CDC*pDC=GetDC(); intnDrawmode=pDC->SetROP2(R2_NOT);//设置异或绘图模式,并保存原来绘图模式pDC->SelectStockObject(NULL_BRUSH);if(m_ist==1){ CPointprePnt,curPnt; prePnt=m_bR;//获得鼠标所在的前一位置
curPnt=point;//绘制橡皮筋线
DrawCircle(pDC,m_bO,prePnt);//用异或模式重复画圆,擦出所画的圆
DrawCircle(pDC,m_bO,curPnt);//用当前位置作为圆周上的点画圆
m_bR=point;}pDC->SetROP2(nDrawmode);//恢复原绘图模式
ReleaseDC(pDC);//释放设备环境
第八步:编译运行程序,验证运行结果。〔例〕编写一个程序Mydrawline,程序
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年砌体抹灰劳务分包合同(含合同解除)3篇
- 用电用煤气安全主题班会
- 《居家老年人健康状况及护理需求调查研究》
- 《我国高水平冰舞运动员耐力素质训练的研究》
- 《《长白山江岗志略》研究》
- 《旅游企业效率工资的效益评估研究》
- 24 古人谈读书(教学实录)2024-2025学年统编版语文五年级上册
- 2024农家乐生态旅游与文化体验合作协议书3篇
- 2024年旅行社服务合同范本3篇带眉脚
- 中华魂中华好家风三分钟演讲稿(14篇)
- 防护用品的使用和维护安全培训课件
- 茶叶店食品安全管理元培训内容
- 人工智能算力中心
- 电路理论:星形联接与三角形联接的电阻的等效变换
- 2023四川省安全员A证考试题库附答案
- 小学生化解冲突心理解康主题班会如何积极的处理冲突 课件
- 无人机飞行规则与安全操控技巧培训
- 2024年全军面向社会公开招考文职人员统一考试《数学2+物理》模拟卷(不含答案)-20231120221552
- 2021年上海市春季高考语文真题试卷(含答案)
- 中国进出口银行在船舶融资中的作用
- 《勤学笃行求知若渴》主题班会课件
评论
0/150
提交评论