1、VC图形编程 2.1 创建应用程序 下面我们介绍建立一个Hello程序的步骤。1.启动VC+6.0,从File菜单中选择New选项,并在对话框中,选择Projects标签,然后单击MFC AppWizard(exe)。在Location域中输入一个合适的路径名或单击Browse按钮来选择一个。在Project name中输入hello作为项目名称。这时候你会看到hello也会出现在Location域中 Hello程序 单击OK按钮,打开MFC AppWizard-Step1对话框。这个对话框用于选择应用程序的基本结构,可以选择单文档界面(SDI)、多文档界面(MDI)和基于对话框的界面。我们在
2、单选框中选择Single document,表 示选择单文档界面,一次只允许在程序中打开一个文件。单击Next按钮,打开MFC AppWizard-Step2 of 6对话框。该对话框用于选择数据库支持环境,本例中我们选择None,表示不需要任何数据库支持 单击Finish按钮,弹出New Project Information 对话框 单击OK按钮,MFC AppWizard 自动生成为程序生成所需的开始文件,并自动在项目工作区打开新项目 建立并运行这个程序,选择Build 菜单下的!Executive hello.exe 2.2.1 图形设备接口(Graphical Device Inte
3、rface,GDI)是windows用来管理图形操作的一个与设备无关的函数库,提供了许多有关图形操作的API函数。Windows图形编程主要是利用图形设备接口(GDI)中的相关函数实现的。2.2 windows图形系统图形系统?设备环境DC(Device Context)又称设备上下文,也称设备描述表。DC实际上是一个关于如何绘制图形的方法的集合,它不仅可以绘制各种图形,而且还可以确定在应用窗口中绘制图形的方式,即确定绘图模式和映射模式。用户在绘图之前,必须获取窗口区域的一个设备环境DC。接着才能进行 GDI函数的调用,执行适合于设备环境DC的命令。2.2.2 设备环境类设备环境类?Windo
4、ws设备环境是GDI的关键元素。它代表了不同的物理设备,一般分为显示器型,打印机型,内存型和信息型。?MFC(Microsoft)类库中提供了设备环境类CDC,CDC封装了Windows的DC,其父类是CObject。?MFC还提供了CDC的派生类CClientDC、CPaintDC、CMetafileDC和CWindowDC.2.2.2 设备环境类设备环境类 CDC类的派生类简介 派生类名称 说 明 CClientDC 这是一个设备描述表,提供对窗口客户区域的图形访问。在窗口中画图时可使用此类DC,但对WM_PAINT Windows消息除外。CMetaFileDC 这个设备描述表代表Win
5、dows元文件,它包含一系列命令已重新产生图像,想要创建独立于设备的文件是可用此类DC,用户可以回放这种文件来创建图像。CPaintDC 这是创建响应WM_PAINT Windows消息的设备描述表。应用程序可以使用此DC更新Windows显示,通常在MFC应用程序的OnPaint()函数中使用。CWindowDC 可以提供在整个窗口(包括客户区和非客户区)中画图的设备描述表。CWindowDC类与CPaintDC和CClientDC类的区别?用CPaintDC类和CClientDC类的对象绘制图形时,绘制区只能是客户区,而不能在非客户区,而CWindowsDC可以在非客户区进行图形绘制。CW
6、indowsDC一般在框架窗口类中(CMainFrame)引用,在视图窗口中引用CwindowsDC类时,由于视图类只能管理客户区,所以并不能在非客户区进行绘制。?在CWindowsDC绘图类下,坐标系是建立在整个屏幕上的,在像素坐标方式下,坐标原点在屏幕的左上角,而在CPaintDC和CClientDC绘图类下,坐标系是建立在客户区上的,在像素坐标方式下,坐标原点在客户区的左上角。CPaintDC与CClientDC类的区别?CPaintDC类应用在OnPaint函数中,以响应Windows的WM_PAINT消息。而CClientDC应用在非响应消息WM_PAINT的情况。CPaintDC类
7、响应WM_PAINT消息,自动完成绘制,这对维护图形的完整性有着重要的作用。例如在一个窗口中,已经绘制了n条直线,这个窗口的完整性可能会被破坏(如被对话框覆盖),当破坏完整性的程序结束时,这个窗口就会接受到一个WM_PAINT消息,得到此消息后,激活消息处理函数(如OnPaint)进行窗口绘制。如果现在想在屏幕上再绘制一条直线,就要用到CClientDC类,这个类可以实时的将图形绘制在屏幕上。CDC类对象的使用方式 1.在视图类的OnDraw成员函数中使用 在视图内绘图最常用的是使用在视图内绘图最常用的是使用OnDraw 函数。该函数是函数。该函数是Cview类中的类中的一个虚函数,每次当视图
8、需要重新绘制时,应用程序框架都会自动调用OnDraw 函数。当用户改变了窗口尺寸,或者当窗口恢复了先前被遮盖的函数。当用户改变了窗口尺寸,或者当窗口恢复了先前被遮盖的部分,或者当应用程序改变了窗口数据时,应用程序框架都会自动调用OnDraw 函数。函数。void CHelloView:OnDraw(CDC*pDC)CPixelDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here pDC-TextOut(100,100,Hello!);2.在视图窗口以外的窗口中使用 窗口类提供WM_P
9、ANT消息响应函数OnPaint,以便绘制或重绘,还必须使用CPaintDC 派生类对象。在使用OnPaint后,OnDraw失效。void CHelloView:OnPaint()CPaintDC dc(this);/device context for painting /TODO:Add your message handler code here 捤吮硥佴瑵?尬 在OnPaint函数中使用);dc.Ellipse(20,20,100,100);/Do not call CView:OnPaint()for painting messages CDC类对象的使用方式 3.在OnDraw与
10、OnPaint以外的消息响应函数中使用 必须使用CClientDC派生类对象,如果函数在支持滚动的视窗中使用,还需调用CscrollView:OnPrepareDC函数。void CMainFrame:On32771()/TODO:Add your command handler code here CClientDC dc(this);捤吮硥佴瑵?尬 在菜单命令消息响应函数中使用);dc.Ellipse(100,200,200,300);CDC类对象的使用方式 CDC类常用的成员函数 1.点 调用CDC类成员函数SetPixel 可以绘制一个点,调用GetPixel可以获取点的颜色。COLO
11、RREF SetPixel(int x,int y,COLORREF crColor);COLORREF SetPixel(POINT point,COLORREF crColor);COLORREF GetPixel(int x,int y)const;COLORREF GetPixel(POINT point,)const;32位的COLORREF类型值来确定图形颜色值,其结构为0 x00bbggrr,bb:代表蓝色值,范围从00到FF;gg:代表绿色值,范围从00到FF;rr:代表红色值,范围从00到FF;还可以用RGB宏来完成相同的功能:RGB(short red,short gree
12、n,short blue)red 代表红色值,范围从0到255;green代表绿色值,范围从0到255;blue代表蓝色值,范围从0到255;CDC类常用的成员函数 void CHelloView:OnDraw(CDC*pDC)CPixelDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);for(int i=0;iSetPixel(1*i,50,RGB(0,0,255);for(int j=0;jSetPixel(2*j,100,(COLORREF)0 x0000ff00);for(int p=0;pSetPixel(5*p,250,(COLORREF)0 x
13、00ff00ff);CDC类常用的成员函数 2.直线 CPoint MoveTo(int x,int y);CPoint MoveTo(POINT point);BOOL LineTo(int x,int y);BOOL LineTo(POINT point);MoveTo移动坐标到当前点 LineTo从当前点到终点画一条直线 CDC类常用的成员函数 void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here pDC
14、-MoveTo(30,30);pDC-LineTo(200,300);CDC类常用的成员函数 3.弧 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);BOOL ArcTo(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);BOOL ArcTo(LPCRECT lpRect,POINT ptStart,POINT ptEnd);x1,y1,x2,y2
15、:边界矩形左上角和右下角坐标 x3,y3,x4,y4:弧线起点和终点坐标 lpRect:指定边界矩形 ptStart:指定弧线起点 ptEnd:指定弧线终点 CDC类常用的成员函数 CDC类常用的成员函数 void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here pDC-Arc(50,50,200,150,10,30,500,200);void CHelloView:OnDraw(CDC*pDC)CHelloDoc
16、*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here CRect rect(45,25,85,150);CPoint pt1,pt2;pt1.x=5;pt1.y=5;pt2.x=250;pt2.y=30;pDC-ArcTo(rect,pt1,pt2);CDC类常用的成员函数 4.折线 BOOL Polyline(LPPOINT lpPoints,int nCount)BOOL PolylineTo(const POINT*lpPoints,int nCount)lpPoints:指定折线的
17、各个顶点坐标 nCount:指定顶点的数目 CDC类常用的成员函数 5.矩形 BOOL Rectangle(int x1,int y1,int x2,int y2);BOOL Rectangle(LPCRECT lpRect);BOOL RoundRect(int x1,int y1,int x2,int y2,int x3,int y3);BOOL RoundRect(LPCRECT lpRect,POINT point);RoundRect:绘制圆角矩形 x3,y3,point:矩形圆角椭圆的宽度和高度 CDC类常用的成员函数 void CHelloView:OnDraw(CDC*pDC)
18、CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here pDC-Rectangle(20,20,100,60);pDC-RoundRect(150,20,200,150,20,15);CDC类常用的成员函数 6.椭圆 BOOL Ellipse(int x1,int y1,int x2,int y2);BOOL Ellipse(LPCRECT lpRect);7.扇形 BOOL Pie(int x1,int y1,int x2,int y2,int x3,int y3);BO
19、OL Pie(LPCRECT lpRect,POINT ptStart,POINT ptEnd);8.多边形 BOOL Polygon(LPPOINT lpPoints,int nCount);CDC类常用的成员函数 void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here pDC-Ellipse(20,70,140,150);CRect rect(250,150,300,100);CPoint pt1,pt2;p
20、t1.x=250;pt1.y=20;pt2.x=300;pt2.y=100;pDC-Pie(rect,pt1,pt2);CPoint p1(340,20);CPoint p2(320,80);CPoint p3(350,120);CPoint p4(420,100);CPoint p5(400,20);CPoint p5=p1,p2,p3,p4,p5;pDC-Polygon(p,5);与绘图相关的GDI对象类 CBitmap类:用于管理、绘制位图资源的类。CPen:用于管理线条绘制的类,通过Cpen类对象,可以设置绘图时的线型、线条宽度、颜色等属性。CBrush:定义了画刷,通过Cbrush对
21、象,可以设置绘制封闭图形的填充色、填充模式等属性。Cpalette:该类用于管理应用程序的调色板,使应用程序的调色板与其他应用程序不干扰。CRgn:该类定义了区域,区域是由一个或多个封闭几何体构成的一个范围,来进行填充、鼠标测试等工作。Cfont:该类用于管理字体,设置绘制文本的字体大小、字体样式等属性。画笔与画刷 画笔是一种用来画线及绘制有形边框的工具,用户可以指定它的颜色及厚度,并且可以指定它画实线、点线或虚线。画刷是用来填充封闭图形的。画笔与画刷.使用库存画笔与画刷 Windows提供的个库存画笔:?BLACK_PEN:黑色画笔?NULL_PEN:空画笔?WHITE_PEN:白色画笔 W
22、indows提供的个库存画刷:?BLACK_BRUSH:黑色画刷?DKGRAY_BRUSH:深灰色画刷?GRAY_BRUSH:灰色画刷?HOLLOW_BRUSH:透明窗口画刷?LTGRAY_BRUSH:浅灰色画刷?NULL_BRUSH:空画刷?WHITE_BRUSH:白色画刷子 通过调用 SelectStockObject 选择画笔或画刷子 void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);CRect rect1(20,20,320,220);CRect rect2(95,95,245,
23、195);CPoint pt;pt.x=pt.y=10;CBrush*pBrush=(CBrush*)pDC-SelectStockObject(KGRAY_BRUSH);pDC-RoundRect(rect1,pt);CPen*pPen=(CPen*)pDC-SelectStockObject(WHITE_PEN);pDC-RoundRect(rect2,pt);pDC-SelectObject(pPen);/恢复画笔 pDC-SelectObject(pBrush);/恢复画刷 画笔与画刷.自定义画笔 调用CPen 类成员函数CPen、CreatePen、CreatePenIndirect
24、可以创建画笔。CPen(int nPenStyle,int nWidth,COLORREF crColor);BOOL CreatePen(int nPenStyle,int nWidth,COLORREF crColor);BOOL CreatePenIndirect(LPLOGPEN lpLogPen);画笔与画刷 nPenStyle:设置画笔的样式。常用样式如下:?PS_SOLID:实线画笔。?PS_DASH:虚线画笔,仅当线宽为1时有效。?PS_DOT:点线画笔,仅当线宽为1时有效。?PS_DASHDOT:点划线画笔,仅当线宽为1时有效。?PS_DASHDOTDOT:双点划线画笔,线宽
25、为1时有效?PS_NULL:空笔不划线。nWidth:指定画笔宽度。画笔与画刷 lpLogPen:指向包含画笔信息的LOGPEN结构变量。LOGPEN结构定义如下:typedef struct tagLOGPEN UNIT lopnStyle;/设置画笔的样式 POINT lopnWidth;/设置画笔的宽度 COLORREF lopnColor;/设置画笔的颜色 LOGPEN;void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native
26、 data here CPen NewPen(PS_SOLID,5,RGB(0,0,255);CPen*pOldPen=pDC-SelectObject(&NewPen);pDC-MoveTo(10,20);pDC-LineTo(500,200);pDC-SelectObject(pOldPen);画笔与画刷 3.自定义画刷 调用CBrush类成员函数CBrush、CreateSolidBush、CreateHatchBrush、CreatePatternBrush和CreateBrushIndirect 等可以创建画刷。CBrush(COLORREF crColor);CBrush(int
27、nIndex,COLORREF crColor);BOOL CreateSolidBrush(COLORREF crColor);BOOL CreateHatchBrush(int nIndex,COLORREF crColor);BOOL CreatePatternBrush(CBitmap*pBitmap);BOOL CreateBrushIndirect(const LOGBRUSH*lpLogBrush);画笔与画刷 nIndex:指定图案的模式。可供选择的模式如下:?HS_BDIAGONAL:从左到右向下成45度的对角线。?HS_CROSS:水平线和垂直线相交的十字交叉线。?HS_D
28、IAGCROSS:夹角为45度的斜十字交叉线。?HS_FDIAGONAL:从左到右向上成45度的对角线。?HS_HORIZONAL:水平阴影线。?HS_VERTICAL:垂直阴影线。pBitmap:指定位图对象 lpLogBrush:指向包含画刷信息的LOGBRUSH结构变量 void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data here CBrush NewBrush1(RGB(0,255,0);CBrush*pOld
29、Brush1=pDC-SelectObject(&NewBrush1);pDC-Rectangle(50,50,200,300);pDC-SelectObject(pOldBrush1);填充图形.绘制矩形边框 void FrameRect(LPCRECT lpRect,CBrush*pBrush);2.用画刷子填充矩形区域 void FillRect(LPCRECT lpRect,CBrush*pBrush);.用指定颜色填充矩形区域 void FillSolidRect(LPCRECT lpRect,COLORREF clr);void FillSolidRect(int x int y,
30、int cx,int cy,COLORREF clr);4.用当前颜色的相反色填充 void InvertRect(LPCRECT lpRect);void CHelloView:OnDraw(CDC*pDC)CHelloDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);CRect rect1(50,50,150,100);CRect rect2(160,50,260,100);CRect rect3(50,110,150,160);CRect rect4(160,110,260,160);CBrush brush1(RGB(0,0,255);CBrush b
31、rush2(RGB(255,0,0);pDC-FillRect(rect1,&brush1);pDC-FrameRect(rect2,&brush2);pDC-FillSolidRect(rect3,RGB(0,255,0);pDC-FillRect(rect4,&brush1);pDC-InvertRect(rect4);2.2 交互设计师.菜单设计.对话框的设计.用鼠标绘图 使用鼠标绘图 在VC中,鼠标的各种事件(单击鼠标左键,单击鼠标右键,双击鼠标左键,双击鼠标右键,移动鼠标)被作为消息,通过系统自带的消息映射功能,对操作者的不同操作进行响应处理。使用鼠标绘图 void CCreateL
32、ineView:OnLButtonDown(UINT nFlags,CPoint point)CDC*pDC=GetDC();/获取设备环境 pDC-SelectStockObject(NULL_BRUSH);/空画刷,选取库存的GDI模式 switch(m_step)case 0:/当第一次单击鼠标左键 m_Step=m_Endp=point;/确定直线的起点 m_step+;/等待输入直线的终点 /m_bline=FALSE;break;使用鼠标绘图 case 1:/当第二次单击鼠标左键 m_Endp=point;/确定直线的终点 m_step=-1;/使得再单击鼠标左键均无效 /m_bl
33、ine=TRUE;/生成直线 DrawLine(pDC,m_Step,m_Endp);/绘制直线 break;default:;ReleaseDC(pDC);/释放不再使用的DC CView:OnLButtonDown(nFlags,point);使用鼠标绘图 void CCreateLineView:DrawLine(CDC*pDC,CPoint start,CPoint end)pDC-MoveTo(start.x,start.y);pDC-LineTo(end.x,end.y);使用鼠标绘图 设置4个成员变量 变量名称 访问类型 数据类型 功能 m_Step protected CPoi
34、nt 直线起始点 m_Endp protected CPoint 直线终止点 m_step protected int 当前直线绘制状态 m_bline protected BOOL 判断是否已经生成直线 使用鼠标绘图 设置橡皮筋模式 void CCreateLineView:OnMouseMove(UINT nFlags,CPoint point)CDC*pDC=GetDC();int nDrawmode=pDC-SetROP2(R2_NOT);/设置绘图模式:屏幕颜色反色。pDC-SelectStockObject(NULL_BRUSH);if(m_step=1&!m_bline)CPoint prePnt,curPnt;prePnt=m_Endp;/获得光标所在的前一个位置 curPnt=point;使用鼠标绘图 DrawLine(pDC,m_Step,prePnt);/绘制橡皮线 DrawLine(pDC,m_Step,curPnt);m_Endp=point;pDC-SetROP2(nDrawmode);/恢复先前的绘图模式 ReleaseDC(pDC);/释放DC