1、实验4 windows绘图实验4 Windows绘图实验目的1、 掌握设备描述表2、 掌握CDC类和CGDIObject类及其派生类的应用3、 掌握CFont类的一个用4、 定时器的应用与定时消息的处理实验内容:本节主要掌握Windows的绘图功能,主要内容包括图形设备接口、CDC类和CGDIObject类、用CDC类进行图形绘制、用CGDIObject类的派生类CPen类和CBrush类进行绘图。还讲述了用CGDIObject类的派生类CFont类设置字体以及用定时器实现简单的动画效果。 1.设备描述表设备描述表(Device Context)是一个用来确定任何设备的GDI出书的位置和形象属
2、性的集合。应用程序病不能直接访问设备描述表,但是应用程序可以使用设备描述表的句柄来间接地存取设备描述表及其属性。创建的设备描述表包含了它所有的属性和默认值。属性默认值相关函数背景色WHITEGetBkColorSetBkColor背景模式OPAQUEGetBkModeSetBkMode位图NONECreateBitmapCreateBitmapIndirectCreateCompatiableBitmapSelectObject画刷WHITE_BRUSHCreateBrushIndirectCreateDIBPatternBrushCreateHatchBrushCreatePatternBr
3、ushCreateSolidBrushSelectObject画刷起始位置(0,0)GetBrushOrgSetBrushOrg剪切域DISPLAY_SCRFACEExcludeClipRectIntersectClipRectOffseClipRgnSelectClipPathSelectClipRgn颜色调色板DEFAULT_PALETTECreatePaletteRealizePalette当前笔的位置(0,0)GetCurrentPositionLineToPolyLineToMoveTo绘图模式R2_COPYPENGetROP2SetROP2字体SYSTEM_FONTCreateFo
4、ntCreateFontIndirectSelectObject字符间距0GetTextCharacterExtraSetTextCharacterExtra映像模式MM_TEXTSetMapModeSetMapMode画笔BLACK_PENCreatePenCreatePenIndirectSelectObject多边形填充模式ALTERANTEGetPolyFillModeSetPolyFillMode缩放模式BLACKONWHITESetStretchBitModeGetStretchBitMode文本颜色BLACKGetTextColorSetTextColor视图范围(1,1)Get
5、ViewportExtSetMapModeSetViewportExtScaleViewportExt视图原点(0,0)GetViewportOrgOffsetViewportOrgSetViewportOrg窗口范围(1,1)GetWindowExtSetMapModeSetWindowExtScaleWindowExt窗口原点(0,0)GetWindowOrgOffsetWindowOrgSetWindowOrg2.坐标系统在Windows环境下,所有图形文字的输出都是基于坐标系统的,图形坐标系统与基于文本的函数所使用的坐标系统是一致的。默认的坐标系统以用户区域的左上角为原点,向右的每一个
6、像素表示沿正X轴的一个单位,向下的每一个像素表示沿正Y轴的一个单位。3.绘图工具绘图工具包括画线的画笔、填充图形内部以及书写正文的字体工具。所有这些工具的使用都要经过3个步骤,即建立工具、选择工具和使用完后删除相应的工具。4.CDC类和CGDIObject类CDC类封装了Windows的DC(设备描述表),是MFC设备环境类的基类,其他的MFC设备环境类都是CDC类的派生类。CDC类指针的生成是用GetDC()函数来实现的,CDC类指针的销毁是用ReleaseDC()函数来实现的。如:CDC *pDC=GetDC(); ReleaseDC(pDC);CGDIObject类及其派生类只封装了GD
7、I中的部分实体,所以CGDIObject类和GDI并不具有想CDC类和DC那样的对应关系。CGDIObject类具有以下几个主要派生类:CBitmap:位图CBrush类:画刷CPen类:画笔CPalette类:调色板CFont类:字体CRgn类:区域构造CGDIObject派生类的对象通用有两种方法:(一)一步构造法。构造和初始化对象都在带参数的构造函数中一步完成,如:CPen myPen(PS_SOLID, 3, RGB(255,0,0); /3个单位粗的红色实线CBrush myBrush(RGB(0,0,255); /蓝色画刷(二)两部构造法。构造和初始化分两步进行,构造由不带参数的构
8、造函数完成,而初始化由初始化函数完成,如:CPen myPen;myPen.CreatePen(PS_DOT,1,RGB(0,0,0); /1个单位粗的黑色点线CBrush myBrush;myBrush CreateSolidBrush(RGB(0,0,255); /蓝色实画刷例1 当单击鼠标左键时,画一个充满整个客户区的椭圆,并画一个左上角为(100,100)、右下角为(200,200)的矩形。步骤如下:(1) 用MFC AppWizard建立一个基于单文档的工程Graphics。(2) 用类向导在CGraphicsView类添加一个左键单击消息WM_LBUTTONDOWN消息处理函数On
9、LButtonDown,代码如下:void CGraphicsView:OnLButtonDown(UINT nFlags, CPoint point) CDC *pDC=GetDC(); CRect rect; GetClientRect(&rect); pDC-Ellipse(&rect); pDC-Rectangle(100,100,200,200); CView:OnLButtonDown(nFlags, point);点左键然后得:例2 增加了刷新支持功能的Graphics绘图。(1) 在CGraphicsView类中增加一个布尔型成员变量m_bLbuttonDown表示鼠标左键单事
10、件的发生,并在构造函数中添加m_bLbuttonDown=FALSE;语句,进行初始化。(2) 将函数OnLButtonDown()修改为以下内容:m_bLbuttonDown=true;Invalidate();(3) 在Ondraw()函数中,添加代码如下:if(m_bLbuttonDown)CDC *pDC=GetDC();CRect rect;GetClientRect(&rect); /获得客户区的位置放在rect中pDC-Ellipse(&rect); /画一个充满整个客户区的椭圆pDC-Rectangle(100,100,200,200); /画一矩形 单击右键得到: 例3 用线
11、宽为3的红色画笔在客户区画一条直线。(1) 用MFC AppWizard建立一个基于MFC单文档的工程ex53。(2) 修改CEx53View类的OnDrwa()函数实现画线,代码如下:void CEx53View:OnDraw(CDC* pDC) CEx53Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); / TODO: add draw code for native data here CPen NewPen; NewPen.CreatePen(PS_SOLID,3,RGB(255,0,0);/创建新画笔 CPen* pOldPen; pOld
12、Pen=pDC-SelectObject(&NewPen); /将新画笔选入设备环境 pDC-MoveTo(100,100); pDC-LineTo(200,200); /用新画笔画一条直线 pDC-SelectObject(pOldPen); / 恢复设备环境中原来的画笔 NewPen.DeleteObject(); 例4 绘图实现单击鼠标左键后,用绿色、垂直水平交叉线画刷填充椭圆内部,步骤如下:(1) 用MFC AppWizard建立一个基于MFC单文档的工程ex54。(2) 用类向导ClassWizard在CEx54View类中添加一个鼠标左键,单击消息WM_LBUTTONDOWN的消息
13、处理函数OnLButtonDown(),编辑代码如下:void CEx54View:OnLButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default CDC *pDC=GetDC(); CBrush newbrush(HS_CROSS,RGB(0,255,0);/创建一个新画刷 CBrush *poldbrush; poldbrush=pDC-SelectObject(&newbrush);/将新画刷选入设备环境 CRect rect; GetClien
14、tRect(&rect); pDC-Ellipse(&rect);/用新画刷画椭圆 pDC-SelectObject(poldbrush);/恢复旧画刷 CView:OnLButtonDown(nFlags, point);(3) 编译、链接并运行程序。单击右键得到:例5 在Windows下利用MFC绘图。(1) 应用AppWizard创建一个基于MFCEXE类型的单文档工程ex55。(2) 找到CEx55View类,并在其OnDraw()函数中添加以下代码:void CEx55View:OnDraw(CDC* pDC) CEx55Doc* pDoc = GetDocument(); ASSE
15、RT_VALID(pDoc); / TODO: add draw code for native data here int i; /绘制一组彩色点 pDC-TextOut(20,20,point); pDC-SetPixel(100,20,RGB(255,0,0); pDC-SetPixel(110,20,RGB(0,255,0); pDC-SetPixel(120,20,RGB(0,0,255); pDC-SetPixel(130,20,RGB(255,255,0); pDC-SetPixel(140,20,RGB(255,0,255); pDC-SetPixel(150,20,RGB(0
16、,255,255); pDC-SetPixel(160,20,RGB(0,0,0); /绘制一组彩色线 /设置颜色表 struct tagColor int r,g,b; color7=255,0,0,0,255,0,0,0,255,255,255,0,255,0,255,0,255,255,0,0,0; /定义两个指向画笔的指针 CPen* pNewPen; CPen* pOldPen; for(i=0;iCreatePen(PS_SOLID,2,RGB(colori.r,colori.g,colori.b) /把新创建的画笔选入设备描述表,同时保存原来的画笔 pOldPen=pDC-Sel
17、ectObject(pNewPen); /用新画笔绘图 pDC-MoveTo(20,60+i*10); pDC-LineTo(160,60+i*10); /恢复设备描述表中的原有画笔 pDC-SelectObject(pOldPen); else AfxMessageBox(Create Pen Error!); delete pNewPen; /删除新画笔,以便再另外分配 /绘制圆弧 for(i=0;iArc(260-5*i,70-5*i,260+5*i,70+5*i,260+5*i,70,260+5*i,70); CBrush* pNewBrush; CBrush* pOldBrush;
18、for(i=8;i1;i-) pNewBrush=new CBrush; if(pNewBrush-CreateSolidBrush(RGB(color8-i.r,color8-i.g,color8-i.b) pOldBrush=pDC-SelectObject(pNewBrush); pDC-Ellipse(260-10*i,200-5*i,260+10*i,200+5*i); pDC-SelectObject(pOldPen); delete pNewBrush; /绘制矩形和圆角矩形 pDC-Rectangle(190,270,250,310); pDC-RoundRect(260,27
19、0,330,310,30,20); (3) 编译、链接并运行程序。例6 绘图实现在鼠标右键单击位置显示一个红底绿字的字符串“文本输出举例!”,步骤如下:(1) 新建一个基于MFC AppWizardexe的单文档工程ex56。(2) 用类向导ClassWizard在CEx56View类添加鼠标右键单击消息WM_RBUTTONDOWN的消息处理函数OnRBuutonDown(),编辑代码如下:void CEx56View:OnRButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/
20、or call default CDC *pDC=GetDC(); pDC-SetBkColor(RGB(255,0,0); pDC-SetTextColor(RGB(0,255,0); pDC-TextOut(point.x,point.y,文本输出举例!); CView:OnRButtonDown(nFlags, point);(3) 编译、链接并运行程序。例7 修改例6,增加使用自定义字体实现单击鼠标右键输出文本。右键消息处理函数修改后内容如下:void CEx57View:OnRButtonDown(UINT nFlags, CPoint point) / TODO: Add your
21、 message handler code here and/or call default CDC *pDC=GetDC(); CFont myfont; /定义CFont类 CFont*oldfont; /定义CFont类的指针 myfont.CreateFont(-50,0,0,0, FW_NORMAL,FALSE,FALSE,FALSE, GB2312_CHARSET, /中文字符集 OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH|FF_MODERN, 楷体); /楷体 oldfont=pDC-S
22、electObject(&myfont); pDC-TextOut(0,50,这是自定义的楷体!); pDC-SelectObject(oldfont); /恢复原始字体 CView:OnRButtonDown(nFlags, point);编译、链接并运行程序,在客户区单击鼠标右键,观察结果。例8 在例7的基础上,使用LOGFONT结构产生新字体。修改鼠标右键消息处理函数如下:void CEx58View:OnRButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or cal
23、l default CDC *pDC=GetDC(); CFont myfont; /定义CFont类 CFont*oldfont; /定义CFont类的指针 LOGFONT font; /定义逻辑字体 memset(&font,0,sizeof(LOGFONT); /给font中的所有数据成员赋值为0 font.lfHeight=-50;/指定字体高度为50 font.lfWeight=FW_NORMAL;/指定字体粗细 font. lfCharSet=GB2312_CHARSET;/字符集 strcpy(font.lfFaceName,楷体);/指定字体 myfont.CreateFont
24、Indirect(&font); /非直接创建字体 oldfont=pDC-SelectObject(&myfont); /把字体选入设备环境,并保留旧字体 pDC-TextOut(100,200,第2种方法创建字体!); pDC-SelectObject(oldfont);/恢复原始字体 CView:OnRButtonDown(nFlags, point);编译、链接并运行。例9 在例7的基础上,使用TEXTMETRIC结构获取字体信息。修改后的消息处理函数如下:void CEx59View:OnRButtonDown(UINT nFlags, CPoint point) / TODO: A
25、dd your message handler code here and/or call default CDC *pDC=GetDC(); CFont myfont; /定义CFont类 CFont*oldfont; /定义CFont类的指针 LOGFONT font; /定义逻辑字体 memset(&font,0,sizeof(LOGFONT); /给font中的所有数据成员赋值为0 font.lfHeight=-50;/指定字体高度为50 font.lfWeight=FW_NORMAL;/指定字体粗细 font. lfCharSet=GB2312_CHARSET;/字符集 strcpy
26、(font.lfFaceName,楷体);/指定字体 myfont.CreateFontIndirect(&font); /非直接创建字体 oldfont=pDC-SelectObject(&myfont); TEXTMETRIC tm;/定义TEXTMETRIC结构tm pDC-GetTextMetrics(&tm);/获取字体信息 CString str; str.Format(字体的高度为%d,tm.tmHeight); /str中存放的内容是字体的高度-50 pDC-TextOut(100,200, 第2种方法创建字体!); /用新字体输出字符串 pDC-SelectObject(ol
27、dfont);/恢复设备环境中的旧字体 pDC-SetTextColor(RGB(255,0,0); pDC-TextOut(100,100,str);/输出str字符串 CView:OnRButtonDown(nFlags, point);编译、链接并运行。例10 利用定时器在窗口内连续绘制圆形,实现简单的动画效果。(1) 新建一个基于MFC AppWizardexe的单文档工程ex510。(2) 在工作去的ClassView页面中,右键单击CMainFrame类,选择Add Member Variable,依次为类增加下列变量:int x1,x2,y1,y2; /圆的RECT参数int c
28、; /坐标增量在CMainFrame的构造函数中,添加初始化代码:x1=x2=400; /假设屏幕分辨率800*600,400位于x轴中心y1=y2=300; /300位于y轴中心c=10; /增量为10(3) 用类向导ClassWizard为CMainFrame类添加一个定时器消息WM_TIMER的消息处理函数OnTimer(),编辑代码如下:void CMainFrame:OnTimer(UINT nIDEvent) / TODO: Add your message handler code here and/or call default CDC *pDC=GetDC(); pDC- E
29、llipse (x1,y1,x2,y2); /画圆函数 x1=x1-c; y1=y1-c*600/800; x2=x2+c; y2=y2+c*600/800; if(x1=400)c=-c; /如果x1到了x轴边缘或中心,则改变增量的符号 CFrameWnd:OnTimer(nIDEvent);(4) 设置定时器。在CEx510App类的InitInstance()函数中return语句前添加定时器函数:m_pMainWnd-SetTimer(10,50,NULL);设置定时器每隔50ms产生一次定时事件。编译、链接并运行程序。是动画:思考与练习1,CDC类有哪些派生类?简述CDC类和CClientDC类的一般使用方法。CPaintDC,CClientDC,CWindowDC,CMetaFileDC CPaintDC: 封装(BeginPaint)和(EndPaint)两个API的调用. CClientDC:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1