第二章VisualC++6.0绘图基础基于MFC的图形编程2.1windows图形系统2.1.1概述在Window环境中,图形设备接口(GraphicalDeviceInterface,GDI)与设备驱动程序实现了设备无关性的图形。GDI是Windows用来管理图形操作的一个与设备无关的模块,提供了许多有关图形操作的API函数。2.1.2设备环境类为了实现设备无关性,Windows提供了设备环境DC(DeviceContext)又称设备上下文,也称设备描述表。DC实际上是一种数据结构,是GDI的一部分。用户在绘图之前,必须获取窗口区域的一个设备环境DC。接着才能进行GDI函数的调用,执行适合于设备环境DC的命令。2.1windows图形系统2.1.3微软基类库MFC:•以C++形式封装的WindowsAPI(ApplicationProgramInterface),包含了一百多个已经定义好的常用类。•类库中提供了设备环境类CDC,CDC封装了Windows的DC,其父类是CObject。•CDC的派生类有:CClientDC、CPaintDC、CMetafileDC和CWindowDC.2.1windows图形系统派生类名称说明CClientDC这是一个设备描述表,提供对窗口客户区域的图形访问。在窗口中画图时可使用此类DC,但对WM_PAINTWindows消息除外。CMetaFileDC这个设备描述表代表Windows元文件,它包含一系列命令已重新产生图像,想要创建独立于设备的文件是可用此类DC,用户可以回放这种文件来创建图像。CPaintDC这是创建响应WM_PAINTWindows消息的设备描述表。应用程序可以使用此DC更新Windows显示,通常在MFC应用程序的OnPaint()函数中使用。CWindowDC可以提供在整个窗口(包括客户区和非客户区)中画图的设备描述表。2.1windows图形系统CWindowDC类与CPaintDC和CClientDC类的区别:用CPaintDC类和CClientDC类的对象绘制图形时,绘制区只能是客户区,而不能在非客户区,而CWindowsDC可以在非客户区进行图形绘制。CWindowsDC一般在框架窗口类中(CMainFrame)引用,在视图窗口中引用CwindowsDC类时,由于视图类只能管理客户区,所以并不能在非客户区进行绘制。在CWindowsDC绘图类下,坐标系是建立在整个屏幕上的,在像素坐标方式下,坐标原点在屏幕的左上角,而在CPaintDC和CClientDC绘图类下,坐标系是建立在客户区上的,在像素坐标方式下,坐标原点在客户区的左上角。2.1windows图形系统CPaintDC类应用在OnPaint函数中,以响应Windows的WM_PAINT消息。而CClientDC应用在非响应消息WM_PAINT的情况。CPaintDC类响应WM_PAINT消息,自动完成绘制,这对维护图形的完整性有着重要的作用。例如在一个窗口中,已经绘制了n条直线,这个窗口的完整性可能会被破坏(如被对话框覆盖),当破坏完整性的程序结束时,这个窗口就会接受到一个WM_PAINT消息,得到此消息后,激活消息处理函数(如OnPaint)进行窗口绘制。如果现在想在屏幕上再绘制一条直线,就要用到CClientDC类,这个类可以实时的将图形绘制在屏幕上。2.1windows图形系统1.启动VC++6.0,从File菜单中选择New选项,并在对话框中,选择Projects标签,然后单击MFCAppWizard(exe)。在Location域中输入一个合适的路径名或单击Browse按钮来选择一个。在Projectname中输入test作为项目名称。2.2MFC上机步骤2.2MFC上机步骤单击OK按钮,打开MFCAppWizard-Step1对话框。这个对话框用于选择应用程序的基本结构,我们在单选框中选择Singledocument,表示选择单文档界面。2.2MFC上机步骤单击Next按钮,打开MFCAppWizard-Step2of6对话框。该对话框用于选择数据库支持环境,本例中我们选择None,表示不需要任何数据库支持。2.2MFC上机步骤单击Finish按钮,弹出NewProjectInformation对话框2.2MFC上机步骤单击OK按钮,MFCAppWizard自动生成为程序生成所需的开始文件,并自动在项目工作区打开新项目2.2MFC上机步骤从【ClassView】面板可以看出CTestApp是应用的主函数类,用来处理消息。MFC中的数据是存储在CTestDoc类文档中结果的显示是在CTestView类中文档类负责管理和维护数据本身视图类负责处理用户鼠标和键盘的操作2.2MFC上机步骤运行程序,选择Build菜单下的!Executivetest.exe2.2MFC上机步骤2.2.1.CDC类对象的使用方式:1.在视图类的OnDraw成员函数中使用在视图内绘图最常用的是使用OnDraw函数。该函数是Cview类中的一个虚函数,每次当视图需要重新绘制时,应用程序框架都会自动调用OnDraw函数。当用户改变了窗口尺寸,或者当窗口恢复了先前被遮盖的部分,或者当应用程序改变了窗口数据时,应用程序框架都会自动调用OnDraw函数。voidCTestView::OnDraw(CDC*pDC){CPixelDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedataherepDC-Ellipse(30,30,100,100);}2.2CDC类的绘图成员函数pDoc通过GetDocument()函数得到了指向文档类CTestDoc的指针。pDC定义为CDC类的指针。使用pDC指针,可以对CDC类的成员函数进行操作。ASSERT_VALID(pDoc)函数使pDoc指针有效。2.在视图窗口以外的窗口中使用窗口类提供WM_PANT消息响应函数OnPaint,以便绘制或重绘,还必须使用CPaintDC派生类对象。在使用OnPaint后,OnDraw失效。voidCTestView::OnPaint(){CPaintDCdc(this);//定义了一个对象dc//TODO:Addyourmessagehandlercodeheredc.TextOut(0,0,在OnPaint函数中使用);dc.Ellipse(20,20,100,100);//DonotcallCView::OnPaint()forpaintingmessages}2.2CDC类的绘图成员函数3.在OnDraw与OnPaint以外的消息响应函数中使用必须使用CClientDC派生类对象,如果函数在支持滚动的视窗中使用,还需调用CscrollView::OnPrepareDC函数。voidCMainFrame::On32771()//菜单命令响应函数{//TODO:AddyourcommandhandlercodehereCClientDCdc(this);dc.TextOut(200,100,在菜单命令消息响应函数中使用);dc.Ellipse(100,200,200,300);}2.2CDC类的绘图成员函数2.2.2绘图函数1.点调用CDC类成员函数SetPixel可以绘制一个点,调用GetPixel可以获取点的颜色。COLORREFSetPixel(intx,inty,COLORREFcrColor);COLORREFSetPixel(POINTpoint,COLORREFcrColor);COLORREFGetPixel(intx,inty)const;COLORREFGetPixel(POINTpoint,)const;2.2CDC类的绘图成员函数32位的COLORREF类型值来确定图形颜色值,其结构为0x00bbggrr,bb:代表蓝色值,范围从00到FF;gg:代表绿色值,范围从00到FF;rr:代表红色值,范围从00到FF;还可以用RGB宏来完成相同的功能:RGB(shortred,shortgreen,shortblue)red代表红色值,范围从0到255;green代表绿色值,范围从0到255;blue代表蓝色值,范围从0到255;2.2CDC类的绘图成员函数voidCTestView::OnDraw(CDC*pDC){CPixelDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);for(inti=0;i200;i++)pDC-SetPixel(1*i,50,RGB(0,0,255));for(intj=0;j200;j++)pDC-SetPixel(2*j,100,(COLORREF)0x0000ff00);for(intp=0;p200;p++)pDC-SetPixel(5*p,250,(COLORREF)0x00ff00ff);}2.2CDC类的绘图成员函数2.直线CPointMoveTo(intx,inty);CPointMoveTo(POINTpoint);BOOLLineTo(intx,inty);BOOLLineTo(POINTpoint);MoveTo移动坐标到当前点LineTo从当前点到终点画一条直线2.2CDC类的绘图成员函数voidCTestView::OnDraw(CDC*pDC){CTestDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedataherepDC-MoveTo(30,30);pDC-LineTo(200,300);}2.2CDC类的绘图成员函数3.弧BOOLArc(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);BOOLArc(LPCRECTlpRect,POINTptStart,POINTptEnd);BOOLArcTo(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);BOOLArcTo(LPCRECTlpRect,POINTptStart,POINTptEnd);x1,y1,x2,y2:边界矩形左上角和右下角坐标x3,y3,x4,y4:弧线起点和终点坐标lpRect:指定边界矩形ptStart:指定弧线起点ptEnd:指定弧线终点2.2CDC类的绘图成员函数voidCTestView::OnDraw(CDC*pDC){CTestDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedataherepDC-Arc(50,50,200,150,10,30,500,200);}2.2CDC类的绘图成员函数voidCTestView::OnDraw(CDC*pDC){CTestDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahereCRectrect(45,25,85,150);CPointpt1,pt2;pt1.x=5;pt1.y=5;pt2.x=250;pt2.y=30;pDC-ArcTo(rect,pt1,pt2);}2.2CDC类的绘图成员函数4.折线BOOLPolyline(LPPOINTlpPoints,intnCount)BOOLPolylineTo(constPOINT*lpPoints,intnCount)lpPoints:指定折线的各个顶点坐标nCount:指定顶点的数目2.2CDC类的绘图成员函数5.矩形BOOLRectangle(intx1,inty1,intx2,inty2);BOOLRectangle(LPCRECTlpRect);BOOL