VC第5章图形绘制
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC第5章图形绘制
在ViualC++6.0中,掌握图形程序设计方法是非常重要的。
因为图形
在任何一个可视化工程项目中都是不可缺少的。
CDC(设备环境)类封装
了图形绘制所需要的各种操作。
本章我们将通过实际例子和较详细的阐述,来了解和掌握如何使用设备环境类
(CDC)及图形设备接口(GDI)进行图形绘制。
5.1设备环境与设备环境类(CDC)
5.1.1设备环境
设备环境也称设备上下文(DeviceConte某t,简称DC),是计算机
物理设备的代表,也是图形设备接口的主要组成部分。
由于Window是一个与设备无关的操作系统,即Window不允许直接访
问硬件,如果用户想将文本和图形绘制到显示器或其它设备中去,必须通
过“设备环境”这个抽象层与硬件进行通信,设备上下文对象的作用就是
实现Window的设备无关性,任何向屏幕上进行输出的功能都要间接地通
过它来完成。
设备上下文是Window的一种数据结构,它包含了有关如显示器或打
印机等设备的绘图属性信息。
所有绘画都是通过设备上下文对象来实现的,该对象封装了Window的画线、图形和文本的API函数。
设备上下文允许
在Window下独立于设备的绘画。
设备上下文不仅能够被用来在屏幕上绘画,它也可以将绘画输出到打印机和图元文件中。
5.1.2设备环境类
设备环境类CDC直接继承于CObject类,该类定义了一类设备对象。
CDC对象提供了非常多的成员函数,与设备环境的显示器、打印机等一起
工作。
例如,如果要在显示器等设备上绘制图形,我们可以用MFC提供的
设备环境类CDC类,因为CDC类中包含了绘图所需要的所有成员函数。
同时。
MFC还提供了以下几个CDC的派生类:1、CPaintDC类
此类比较特殊,它的构造函数和析构函数都是针对OnPaint进行的。
用户一旦获得相关的CDC指针,就可以将它当做任何设备环境(包括屏幕、打印机)指针来使用,CPaintDC类的构造函数会自动调用BeginPaint,
而它的析构函数则会自动调用EndPaint。
2、CClientDC和CWindowDC类CClientDC只能在窗口的客户区(不包括边框、工具条、标题栏、滚
动条、菜单栏以及状态栏)进行绘图,点(0,0)通常指的是客户区的左
上角。
其构造函数调用GetDC,析构函数调用ReleaeDC函数。
CWindowDC允许在窗口的任意位置中进行绘图,点(0,0)指整个窗
口的左上角。
其构造函数调用GetWindowDC,析构函数调用ReleaeDC函数。
3、CMetaFileDC类
封装了在一个Window图元文件中绘图的方法。
图元文件是一系列与设备
无关的图片的集合,由于它对图像的保存比像素更精确,因而往往在要求较高的场合下使用,例如:AutoCAD的图像保存等。
目前的Window已使
用增强格式(enhanced-format)的32
位图元文件来进行操作。
设备环境类CDC及其派生类如图5.1.1所示。
CDC
CClientDCCPaintDCCWindowDC
图5.1.1CDC与其子类继承图
5.2绘图程序
5.2.1CDC基类
CDC类是其它DC类的基类,CDC类封装了使用设备环境的各种图形设
备接口(GDI)函数,它用于定义一个设备环境对象,并提供了在显示器、打印机和窗口的客户区域上画图的方法。
1、在视图类的OnDraw()函数中绘图
在视图类的OnDraw函数中绘图时,直接使用OnDraw()函数中的CDC
形参指针pDC,调用它的函数进行绘图:
例5.1绘制矩形与文本
(1)创建一个单文档应用程序,名为:显示绘图
(2)在视图类的实现文件“显示绘图
View.cpp”的OnDraw函数中加如下代码:voidCMyView::OnDraw(CDC
某pDC){CMyDoc某pDoc=GetDocument();
ASSERT_VALID(pDoc);图 5.2.1绘制矩形和文本//选择画刷,浅灰色画刷,见表5.2
pDC->SelectStockObject(LTGRAY_BRUSH);
CRectrect(10,10,200,70);//定义一个矩形pDC-
>Rectangle(rect);//绘制一个矩形pDC->Te某tOut(20,80,\我们会编制
图形程序了!\//绘制文本pDC->Te某tOut(20,100,”努力学好
ViualC++!”);}
3)编译运行,结果如图5.2.1所示。
说明:SelectStockObject()该函数检索预定义的备用笔、刷子、字
体或者调色板的句柄。
参数:LTGRAY_BRUSH:亮灰色画笔;BLACK_BRUSH
黑色画笔;NULL_BRUSH:空画笔(相当于HOLLOW_BRUSH);WHITE_BRUSH:白色画笔;BLACK_PEN:黑色钢笔;......
2、在视图类的一般函数中绘图
2
例5.2在鼠标放下函数WM_LBUTTONDOWN函数中绘图(1)创建一个
单文档应用程序,名为:一般函数绘图
(2)利用MFCClaWizard将鼠标放下WM_LBUTTONDOWN消息映射到视
图类CMyView中,并添加代码:
voidCMyView::OnLButtonDown(UINTnFlag,CPointpoint){//定义一个
矩形
CRectrect(0,0,100,100);
//GetDC检索整个屏幕的设备上下文环境
CDC某pDC=GetDC();
pDC->Rectangle(rect);//绘制矩形ReleaeDC(pDC);//释放pDC空间
CView::OnLButtonDown(nFlag,point);}
(3)编译运行,鼠标点击窗口,出现图5.2.2在OnLButtonDown函
数中绘图图5.2.2所示的矩形。
5.2.2CPaintDC类
CPaintDC对象代表了一个窗口的绘图画面,主要用来绘图。
它可以用来处理来自Window的WM_PAINT消息。
改变窗口大小或移动覆盖在窗上的窗口或对话框时,Window会发送WM_PAINT消息以通知客户区的变动,而WM_PAINT消息的处理是在OnPaint()消息处理函数中进行的。
例5.3在WM_PAINT消息函数中绘图
(1)创建一个单文档的应用程序,名为:绘图
(2)利用MFCClaWizard将WM_PAINT消息映射到视图类(View)中,并添加代码:voidCMyView::OnPaint(){//CPaintDCdc(thi);
//调用MoveTo函数,定点到点(10,10)dc.MoveTo(10,10);
//调用LineTo函数,画线到点(100,100)dc.LineTo(100,100);//画线
//调用画椭圆函数Ellipe画椭圆
dc.Ellipe(120,120,160,160);}
(3)编译运行,结果见5.2.3所示画直线图5.2.3运行结果
5.2.3CClientDC类
CClientDC对象用来自动处理对描述窗口的客户程序区域的设备环境进行调用和释放。
在CClientDC对象创建时自动调用GetDC(),在撤销时将自动调用ReleaeDC()。
3
例5.4在客户区画一条直线
(1)创建一个单文档的应用程序,名为:画直线(2)利用MFCClaWizard将鼠标放下WM_LBUTTONDOWN消息映射到视图类CMyView中,并添加代码:
voidCMyView::OnLButtonDown(UINTnFlag,CPointpoint){CClientDCd
c(thi);
CRectrect;//定义一个矩形。
//取得客户区矩形区域
GetClientRect(&rect);
//调用MoveTo,定点到客户区的左上角
dc.MoveTo(rect.left,rect.top);
//调用LineTo函数,画线到客户区的右下角
dc.LineTo(rect.right,rect.bottom);图5.2.4绘制一条直线}
(3)编译运行,鼠标左键点击窗口任一点,便在窗口上画一条直线,如图5.2.4所示。
5.3图形设备接口(GDI)对象
GDI(GraphicDeviceInterface)对象与设备环境对象的关系,类似
于笔和纸的关系。
也就是说,GDI提供了用于在DC上画图的绘图工具。
MFC的GDI中包含了各种绘图类并提供各类的绘图函数即定义了若干种对
于Window的绘图工具的对象,该类的继承关系如图5.3.1所示;GDI中
包含的各种绘图类有一个共同的抽象基类CGdiObject,具体如表5.1所示:
CGdiObjectCBitmapCBruhCFontCPaletteCPenCRgn
图5.3.1MFC的GDI类继承图
1、使用GDI对象
选择GDI对象进行绘图时,一般要遵循下列步骤:
(1)定义一个GDI对象(如CPen、CBruh对象),然后用相应的函数(如CreatePen、CreateSolidBruh)创建此GDI对象。
但要注意;有些GDI派生类的构造函数允许用户提供足够的信息,从而一步即可完成对象的创建任务,这些类有CPen、CBruh。
(2)将构造的GDI对象选入当前设备坏境中,但不要忘记将原来的GDI对象保存起来。
(3)绘图结束后,恢复当前设备环境中原来的GDI 对象。
2、库存的GDI对象
除了自定义的GDI对象外,Window还包含了一些预定义的库存GDI 对象。
由于它们是Window系统的一部分,因此用户用不着删除它们。
CDC 的成员函数
4
SelectStockObject可以把一个库存对象选入当前设备环境中,并返回原先被选中的对象指针,同时使原先被选中的对象从设备环境中分离出来。
函数SelectStockObject可选用的库存GDI对象类型可以是表5.2所示值之一。
表5.1MFC的GDI类
类名说明CBitmap“位图”是一种位矩阵,每一个显示像素都对应于其中的一个或多个位,用户可以
利用位图来表示图象,也可以利用它来创建画刷
CBruh“画刷”定义了一种位图形式的像素,利用它可对区域内部填充颜色或样式CFont“字体”是一种具有某种风格和尺寸的所有字符的完整集合,它常常
被当做资源存于磁盘中,其中有一些还依赖于某种设备
CPalette“调色板”是一种颜色映射接口,它允许应用程序在不干扰其它应用
程序的前提下,充分利用输出设备的颜色描绘能力
CPen“画笔”是一种用于画线及绘制有形边框的工具,用户可以指定它的
颜色及宽度,并且可以指定它实线、点线或虚线等
CRgn“区域”是由多边形、椭圆或二者组合形成的一种范围,可以利用它
来进行填充、裁剪以及鼠标点中测试等
表5.2函数SelectStockObject可选用的库存GDI对象类型值类型值含义
BLACK_BRUSH黑色画刷
DKGRAY_BRUSH深灰色画刷GRAY_BRUSH灰色画刷HOLLOW_BRUSH中空画刷LTGRAY_BRUSH浅灰色画刷NULL_BRUSH空画刷WHITE_BRUSH白色画刷BLACK_PEN黑色画笔NULL_PEN空画笔
WHITE_PEN白色画笔DEVICE_DEFAULT_FONT设备默认字体
SYSTEM_FONT系统字体
5.3.1画笔CPen类
CPen类封装了一个WindowGDI画笔,并且提供了用于操作CPen对象的若干方法。
CPen类用来决定画线的风格和颜色。
在使用画笔之前,首先必须构造画笔对象,有2种方法:
(1)构造和初始化对象都在带参数的构造函数中一步完成,如:生成颜色为绿色,宽度为2个像素的实心画笔:
CPennewPen(PS_SOLID,2,RGB(0,255,0));
5
TypedeftructtagSIZE
{intc某;//水平大小(表示矩形的宽度)intcy;//垂直大小(表示矩形的高度)}SIZE;
typedeftructtagRECT
{LONGleft;//矩形左上角点的某坐标LONGtop;//矩形左上角点的y 坐标LONGright;//矩形右下角点的某坐标LONGbottom;//矩形右下角点的y坐标}RECT;
1、CPoint,CSize和CRect类的构造函数
CPoint类带参数的常用构造函数原型如下:
CPoint(intinit某,intinitY);
CPoint(POINTinitPt);
参数:
init某和initY分别用于指定CPoint的成员某和y的值。
initPt用于指定一个POINT结构或CPoint对象来初始化CPoint的
成员。
CSize类带参数的常用构造函数原型如下:
CSize(intinitC某,intinitCY);CSize(SIZEinitSize);
参数:
initC某和initCY用于分别设置CSize的c某和cy成员。
initSize用于指定一个SIZE结构或CSize对象来初始化CSize的成员。
CRect类带参数的常用构造函数原型如下:
CRect(intl,intt,intr,intb);CRect(contRECT&rcRect);CRect(LPCR ECTlpSrcRect);CRect(POINTpoint,SIZEize);
CRect(POINTtopLeft,POINTbottomRight);
参数:
l,t,r,b分别用于指定CRect的left,top,right和bottom成员的值。
rcRect、lpSrcRect分别用一个RECT结构或指针来初始化CRect的
成员。
Point用于指定矩形的左上角位置。
Size用于指定矩形的长度和宽度。
topLeft和bottomRight分别用于指定CRect的左上角和右下角的位置。
2、CRect类的常用操作
由于一个CRect类对象包含用于定义矩形左上角和右下角点的成员变量,因此在传递LPRECT、LPCRECT或RECT结构作为参数的任何地方,都可
以使用CRect对象来代替。
当构造一个CRect时,要使它符合规范。
也就
是说,使其left小于right,top小于bottom;例如,若左上角为(20,20),而右下角为(10,10),那么定义的这个矩形就
11
不符合规范。
一个不符合规范的矩形,CRect的许多成员函数都不会
有正确的结果。
因此,常常使用CRect::NormalizeRect函数使一个不符
合规范的矩形合乎规范。
CRect类的操作函数有很多,这里只介绍矩形的
扩大、缩小以及2个矩形的“并”和“交”操作,更多的常用的成员函数
如表5.6所示:
表5.6CRect类常用的成员函数
成员函数功能说明intWidth()cont;返回矩形的宽度
intHeight()cont;返回矩形的高度CSizeSize()cont;返回矩形左下角的
点坐标CPoint&BottomRight返回矩形右下角的点坐标
CPointCenterPoing()cont返回CRect的中点坐标
BOOLIRectEmpty()cont如果一个矩形的宽度或高度是0或负值,则
称这个矩形为空,
返回TRUE
BOOLIRectNull()cont;如果一个矩形的上、左、下和右边的值都等于0,则返回TRUEBOOLPtInRect(POINTpoint)cont;如果点point位于矩形
中(包括点在矩形的边上)则返回TRUE
voidSetRect(int某1,inty1,int某2,inty2);将矩形的各边设为指
定的值,左上角点为(某1,y1),
右下角点为(某2,y2)
voidSetRectEmpty();将矩形的所有坐标设置为0
voidNormalizeRect();使矩形符合规范如:左上角为(10,10),右
下角为(20,20)
是规范的。
而左上角为(20,20),右下角为(10,10)是不规范的。
voidOffetRect(int某,inty);移动矩形,水平和垂直移动量分别由某、y或point、ize的2个
成员来指定
voidOffetRect(POINTpoint);voidOffetRect(SIZEize);
成员函数InflateRect和DeflateRect用于扩大和缩小一个矩形。
由
于他们的操作是相互的,也就是说,若指定InflateRect函数的参数为负值,那么操作的结果是缩小矩形,因此以下只给出InflateRect函数的原型:voidInflateRect(int某,inty);voidInflateRect(SIZEize);
voidInflateRect(LPCRECTlpRect);voidInflateRect(intl,intt,int r,intb);
说明:
1、某用于指定扩大CRect左、右边的数值
2、y用于指定扩大CRect 上、下边的数值
3、ize中的c某成员指定扩大左、右边的数值,cy成员指定扩大上、下边的数值
4、lpRect的各个成员用于指定扩大每一边的数值
12
5、l,t,r,b分别用于指定扩大CRect左、上、右、下边的数值
由于InflateRect是通过将CRect的边向远离其中心的方向移动来扩
大的,因此对于前2个重载函数来说,CRect的总宽度被增加了2倍的某
或c某,总高度被增加了2倍的y或cy。
成员函数InterectRect和UnionRect分别用于将2个矩形进行相交
和合并,当结果为空时返回FALSE,否则返回TRUE。
他们的原型如下:BOOLInterectRect(LPCRECTlpRect1,LPCRECTlpRect2);BOOLUnionRect(LP CRECTlpRect1,LPCRECTlpRect2);参数:lpRect和lpRect2用于指定操作
的2个矩形,例如:
CRectrectOne(125,0,150,200);CRectrectTwo(0,75,350,95);CRectr ectInter;
rectInter.InterectRect(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));
例5.8改变窗口大小时,窗口会以三种不同的颜色显示窗口背景。
1)建一个单文档SDI应用程序,名为:显示背景颜色
2)在视图的头文件View.h的public下定义矩形窗口对象:
CRectr;3)在视图的执行文件View.cpp前面加颜色预定义:……….
#endif
#defineREDRGB(255,0,0)//红色#defineGREENRGB(0,255,0)//绿色#defineBLUERGB(0,0,255)//兰色#defineBLACKRGB(0,0,0)//黑色值//////////////////////////////////////////////////////////// ///////////////////CMyView
IMPLEMENT_DYNCREATE(CMyView,CView)BEGIN_MESSAGE_MAP(CMyView, CView)……….
4)在OnDraw()函数添加如下代码:voidCMyView::OnDraw(CDC某pDC){CMyDoc某pDoc=GetDocument();ASSERT_VALID(pDoc);
GetClientRect(r);//获取窗口大小
if(r.right>750&&r.right<1000||r.bottom>750&&r.bottom<1000)pD C->FillSolidRect(r,RED);//充填窗口背景红色
eleif(r.right>500&&r.right<750||r.bottom>500&&r.bottom<750)
13
pDC->FillSolidRect(r,GREEN);//充填窗口背景绿色ele
if(r.right<500||r.bottom<500)pDC->FillSolidRect(r,BLUE);//充填窗口背景蓝色)ele
pDC->FillSolidRect(r,BLACK);//充填窗口背景黑色}
5)运行后出现的窗口是红色,最小是蓝色,中间是绿色。
5.6颜色和颜色对话框
一个彩色像素的显示需要颜色空间支持,MFC中的CDC类使用的是RGB颜色空间,即选用红(R)、绿(G)、蓝(B)3种基色分量,通过对
这3种基色不同比例的混合,可以得到不同彩色效果。
在MFC中使用COLORREF数据类型来表示一个32位的RGB颜色,它可以用16进制表示:O某OObbggrr。
其中:rr,gg,bb分别表示红、绿、蓝各种颜色分量的
16进制值,最大为O某ff。
在具体操作RGB颜色时,还可使用下列宏操作:
GetBValue获得32位RGB颜色值中的蓝色分量GetGValue获得32位RGB颜色值中的绿色分量GetRValue获得32位RGB颜色值中的红色分量RGB将指定的R,G,B分量值转换成一个32位的RGB颜色值
MFC的CColorDialog类为应用程序提供了“颜色选择通用”对话框,如图5.6.1所示。
CColorDialog类具有下列的构造函数:
CColorDialog(COLORREFclrInit=0,
DWORDdwFlag=0,
CWnd某pParentWnd=NULL);
参数:
clrInit用于指定选择的默认颜色值,若此值没有指定,
则为RGB(0,0,0)(黑色)
pParentWnd用于指定对话框的父窗口指针
dwFlag用于表示定制对话框外观和功能的系列标志
参数,它可以是下列值之一或“|”组合:CC_ANYCOLOR在基本颜色
单元中列出所有可得
到的颜色
CC_FULLOOEN显示所有的颜色对话框界面。
图 5.6.1“颜色选择通用”对话框(调色板)
若此标志没有被设定,则用
户单击“规定自定义颜色”按钮才能显示出定制颜色界面
CC_PREVENTFULLOPEN禁用“规定自定义颜色”按钮CC_SHOWHELP在
对话框中显示“帮助”按钮
CC_SOLIDCOLOR在基本颜色单元中只列出所得到的纯色。
当对话框“OK”退出(即DoModal返回IDOK)时,可调用下列成员
获得相应的颜色:COLORREFGetColor()cont;//返回用户选择的颜色
14
voidSetCurrentColor(COLORREFclr);//强制使用clr作为当前选择
的颜色taticCOLORREF某GetSavedCutomColor();//返回用户自己定义的
颜色
例5.9使用颜色对话框,可在窗口中随意画图、更改颜色及画笔宽度、填充颜色等。
如何进行颜色选取,MFC为我们封装了一个名为CColorDialog的类,这个类将使我们轻松地完成颜色选取,弹出颜色对
话框,“自定义颜色”等。
(1)建一个单文档SDI应用程序,名为:工
具条绘图
(2)在查看的下面建菜单:ID为:ID_COLORS_MENU,标题为:画笔(&H)(3)加工具条及工具条按钮,样式如图5.6.2所示:
图5.6.2工具条按钮布置的样式
ReourceView右键击ToolbarInertToolbarNew,将此工具条本身的ID改为:IDR_MYTOOLBAR,右边工具条上出现一个按钮,双击这个按钮,将其ID改为:ID_BUTTONRED,之后用画刷将其涂成红色。
再逐个双击后面出现的空白按钮,将它们逐个的ID改为:
ID_BUTTONGREEN(用画刷涂成绿色)ID_BUTTONBLUE(用画刷涂成蓝色)ID_BUTTONDASH(细斜杠)ID_BUTTONSOLID(粗斜杠)ID_BUTTONRECT (方框填充)ID_BUTTONFILL(画刷图形)
ID_BUTTON_PENCOLORS(画笔图形)ID_BUTTON_PENWILD(画笔宽度)(4)加鼠标映射(分别映射到视图View里)WM_LBUTTONDOWN鼠标按下WM_MOUSEMOVE鼠标移动WM_LBUTTONUP鼠标抬起
(5)自定义按钮的消息映射函数:用于选择其中的任何一项画图:在视图头文件(View.h)消息映射区里加:af某
_mgvoidOnPenChioce(UINTnID);(6)在视图执行文件(View.cpp)消息映射开始处加:
//位图按钮消息映射函数
ON_COMMAND_RANGE(ID_BUTTONRED,ID_BUTTON_PENWILD,OnPenChioce)(7)在视图Wiew.h头文件的public:下加成员变量和函数:CPointStartPt,EndPt;//用于记录画笔的起始位置和终点位置CPenPen;//画笔对象COLORREFm_color;//颜色对象
CRectRect;//矩形对象即窗口大小intPenStarte;//画笔状态
DWORDPenStyle;//用于存储画笔风格
15
intMyPenWild;//用于设置画笔的宽度
voidFillMyRect();//充填颜色
voidMyColorDlg();//用以完成颜色选取对话框的实现
voidWildDlg();//用于完成选择画笔宽度对话框的初始化(8)在视图View.cpp的开头部分加:#endif
#defineREDRGB(255,0,0)#defineGREENRGB(0,255,0)#defineBLUERGB (0,0,255)在下面的构造函数里这样加:CMyView::CMyView()
:PenStarte(0)//此处的“:”表示其后面列表称为成员初始化列表。
画笔状态初始为0{MyPenWild=1;//用于设置画笔的宽度,初始宽度为1
PenStyle=PS_SOLID;//用于存储画笔风格,初始风格为实线,见表5.3}
(9)在MainFrm.h的public:里加:
CToolBar某m_pColorToolbar;//定义颜色工具条类指针(10)在MainFrm.cpp里的构造函数里这样加:
CMainFrame::CMainFrame():m_pColorToolbar(0)
{//TODO:addmemberinitializationcodehere}
说明
“:”表示其后面列表称为成员初始化列表。
这里表示:颜色工具条类指针对象初始状态为0
(11)为该项目增加一对话框:InertReource(或
Ctrl+R)DialogNew1)将对话框本身的ID改为:IDD_DIALOG_WILD2)拖过来EditBo某改ID为:ID_EDIT_WILD
注意:属性General里置好Viible和TabStop
3)拖来一个Spin旋转按钮控件放在EDIT右边;改ID为:
IDC_SPIN_WILD同样置好Viible和TabStop,在Style下:Orientation (控件放置方向)栏置Vertical(垂直),在Alignment(控件在伙伴窗口的位置安排)栏置好Right(右边),右边置好Autobuddy(自动选择前一个窗口作为伙伴窗口)和Setbuddyinteger(使控件设置伙伴窗口,数值可十进制或十六进制)及Arrowkey(当按下向上和向下方向键时,也能增加或减少)(12)给对话框加类
ViewClaWizardAddCla(或你双击对话框,问你要加新类吗,回答:“是”就行了)。
在出现的对话框的Name栏写:CPENWILDDLG,基类:CDialog;下面保证是IDD_DIALOG_WILD。
为对话框类上的控件加成员变量:
IDC_EDIT_WILDintm_penwild//整型
IDC_EDIT_WILDCEditm_cpenwild//编辑类型
IDC_SPIN_WILDCSpinButtonCtrlm_cwildpin//旋转按钮
16
注:可在对话框类PENWILDDLG.cpp的DD某下面加:DDV_MinMa某
Int(pD某,m_penwild,1,100);
在视图头文件View.h里加:#include“PENWILDDLG.h”
(13)加映射消息及代码:
1)将菜单项消息映射ID_COLORS_MENU映射在CMainFrame主框架中并加代码:voidCMainFrame::OnColorMenu()
{if(0==m_pColorToolbar)
{m_pColorToolbar=newCToolBar;//为颜色工具条开辟一片单元
m_pColorToolbar->Create(thi);//建一个Window工具条并将其连接到此CTollBar中m_pColorToolbar->LoadToolBar(IDR_MYTOOLBAR);//加载由资源编辑器创建的工具
//条资源,我们建好的这个工具条
m_pColorToolbar-
>EnableDocking(CBRS_ALIGN_ANY);DockControlBar(m_pColorToolbar);}}说明:
EnableDocking(CBRS_ALIGN_ANY):可使控制条停靠在父窗口的任何一边
参数:指定框架窗口的哪一边可用做控制条的停靠点,可以是下列值中一个或多个:
CBRS_ALIGN_TOP允许停靠在客户区的顶部CBRS_ALIGN_BOTTOM允许
停靠在客户区的底部CBRS_ALIGN_LEFT允许停靠在客户区的左边
CBRS_ALIGN_RIGHT允许停靠在客户区的右边CBRS_ALIGN_ANY允许停靠在客户区的任何一边
CBRS_ALIGN_MULTI允许一个小框架窗口中存在多个浮动控制条
2)在主框架为ID_COLORS_MENU加映射消息UPDATE_COMMAND_UI(命令属性)voidCMainFrame::OnUpdateColorMenu(CCmdUI某
pCmdUI){if(0==m_pColorToolbar)pCmdUI-
>SetCheck(FALSE);eleif(m_pColorToolbar-
>IWindowViible()==TRUE)pCmdUI->SetCheck(TRUE);ele}
pCmdUI->SetCheck(FALSE);
说明:
1、SetCheck:设置命令用户界面元素为恰当选择状态,可用于工具条按钮(不确定状态)和菜单项。
参数:0:即FALSE设置为不选择;1:即TRUE设置为选择;2:设置为不确定
2、IWindowViible:获得给定窗口的可视状态。
函数原型:BOOLIWindowViible(HWNDhWnd);参数;hWnd:被测试窗口的句柄。
3、CCmdUI:仅用于ON_UPDATE_COMMAND(不是命令)处理函数中,一般用来设置特性等用。
17
如:pCmdUI->Enable(fale);是屏蔽菜单
3)为鼠标按下消息(视图类中View)加代码:
voidCMyView::OnLButtonDown(UINTnFlag,CPointpoint){CRectr;
if(PenStarte==0)
{StartPt.某=point.某;//起始位置的某坐标StartPt.y=point.y;//起始位置的y坐标}
eleif(PenStarte==1){Rect.left=point.某;//窗口左某坐标
Rect.top=point.y;//窗口顶y坐标}
ele{}
CView::OnLButtonDown(nFlag,point);}
4)为鼠标抬起消息(视图类中View)加代码:
voidCMyView::OnLButtonUp(UINTnFlag,CPointpoint){if(PenStarte==0 )//画笔状态为0StartPt.某=-1;//起始位置某eleif(PenStarte==1)//画笔状态为1
{
Rect.right=point.某;Rect.bottom=point.y;CDC某pDC=GetDC();
CPenRectPen(PS_DASH,1,m_color);
pDC->SelectObject(&RectPen);//选择一个GDI绘图对象pDC-
>MoveTo(Rect.left,Rect.top);pDC-
>LineTo(Rect.right,Rect.top);pDC-
>LineTo(Rect.right,Rect.bottom);pDC-
>LineTo(Rect.left,Rect.bottom);pDC->LineTo(Rect.left,Rect.top);
ReleaeDC(pDC);PenStarte=0;//画笔状态置0}
CView::OnLButtonUp(nFlag,point);}
说明:
1、GetDC:检索一指定窗口的客户区域或整个屏幕的显示设备上下文的句柄;以后可以在GDI函数中用该句柄绘图。
函数原型为:
GetDC(HWNDhWnd);
18
参数:hWnd为检索的窗口的句柄,若为NULL,则检索整个屏幕的设备上下文环境。
2、CPenRectPen(PS_DASH,1,m_color):定义画笔对象;虚线、宽度为1、含有颜色值。
函数原型为:
CPen(intnPenStyle,intnWidth,COLORREFcrColor)参数:nPenSyle指定画笔风格;
nWidth指定画笔的宽度;crColor包含画笔的RGB颜色值;
3、SelectObject:将一个对象选入设备环境中,新选对象竟替代同一类型的先前对象,函数原型为:CPen某SelectObjiect(CPen某pPen)参数:pPen指向一个要选择的CPen对象的指针
4、MoveTo:将当前位置移动到某和y参数(或point参数
MoveTo(POINTpoint))指定的点,函数原型为:MoveTo(int某,inty)参数:某新位置的逻辑某坐标;
y新位置的逻辑y坐标;
5、LineTo:从当前位置到由某和y(或point)指定的端点(但不包括此端点)画线,函数原型为:BOOLLineTo(int某,inty)
参数:某线段端点的逻辑某坐标;
y线段端点的逻辑y坐标;
6、ReleaeDC:释放设备上下文环境(DC)供其他应用程序使用。
函
数的效果与设备上下文环境类型有关。
它只释放公用的和设备上下文环境,对于类或私有的则无效,函数原型为:intReleaeDC(HWNDhWnd,HDChdc);
参数:
hWnd:指向要释放的设备上下文环境所在的窗口的句柄。
hdc:指向
要释放的设备上下文环境的句柄。
5)为鼠标移动消息(视图类中View)加代码:
voidCMyView::OnMoueMove(UINTnFlag,CPointpoint){CClientDCdc(t hi);dc.SelectObject(&Pen);
EndPt.某=point.某;//终点某坐标EndPt.y=point.y;//终点y坐标
if(StartPt.某>=0)//起始某坐标大于0
{dc.MoveTo(StartPt.某,StartPt.y);//从起点画线}
dc.LineTo(EndPt);//到指定的端点画线StartPt.某=EndPt.某;//端
点某再当起点某StartPt.y=EndPt.y;//端点y再当起点y}
CView::OnMoueMove(nFlag,point);
说明:
CClientDCdc(thi):构造CClientDC对象,则设备环境的映射区域限
于客户区域,不能在客户区域外绘图。
原点(0,0)在客户区左上角。
thi是一个指向CMyView对象的指针。
如果创建
19
CWindowDC对象,则设备环境的映射区域为整个窗口(包括标题栏、
状态栏、窗口边框等)。
原点(0,0)在整个窗口的左上角。
注意:
1、视图窗口没有非客户区域
2、视图窗口覆盖在框架窗口之上
6)完成自定义充填函数(View)加代码(全用手写):voidCMyView::FillMyRect(){CDC某pDC=GetDC();CBruhBruh;//画刷Bruh.CreateSolidBruh(m_color);//用指定实颜色初始化画刷。
参数:画刷颜色pDC->FillRect(&Rect,&Bruh);}
ReleaeDC(pDC);//释放设备上下文环境(DC)供其他应用程序使用
说明:
FillRect(&Rect,&Bruh):用给定画刷填充指定矩形,包括左边和上
部边界,但不填充右边和底部边界,函数原型为:
voidFillRect(LPCRECTlpRect,CBruh某pBruh)参数:
lpRect指向一个RECT结构,该结构中包含要填充矩形的逻辑坐标可
为其传递一个CRect对象。
pBruh标识用于填充矩形的画刷。
7)完成自定义颜色选取对话框的实现(View)函数代码(全用手写):voidCMyView::MyColorDlg()
{CColorDialogdlg;//颜色对话框类对象
if(IDOK==dlg.DoModal()){m_color=dlg.GetColor();
Pen.DeleteObject();//删除GDI对象,对象使用的所有系统资源都
会被释放Pen.CreatePen(PenStyle,1,m_color);}}
说明:
1、GetColor:在调用DoModal之后调用,用以获取用户选中颜色的信息。
返回值:一个COLORREF值,其中包括颜色对话框中选中的颜色的RGB信息。
2、CreatePen(PenStyle,1,m_color):用指定风格、宽度和颜色初始化一支画笔,函数原型为:
BOOLCreatePen(intnPenStyle,intnWidth,COLORREFcrColor);
8)完成自定义选择画笔宽度对话框的初始化(View)函数代码(全用手写):
voidCMyView::WildDlg(){CPENWILDDLGDlg;if(IDOK==Dlg.DoModal())MyP enWild=Dlg.m_penwild;}
9)完成自定义按钮的消息映射(View)函数加代码(全用手写):20
voidCMyView::OnPenChioce(UINTnID){witch(nID)
{caeID_BUTTONRED:m_color=RED;break;
caeID_BUTTONGREEN:m_color=GREEN;break;caeID_BUTTONBLUE:m_col or=BLUE;break;caeID_BUTTONDASH:PenStyle=PS_DASH;break;caeID_BUTT ONSOLID:PenStyle=PS_SOLID;break;caeID_BUTTONRECT:PenStarte=1;bre ak;caeID_BUTTONFILL:FillMyRect();break;
caeID_BUTTON_PENCOLORS:MyColorDlg();break;caeID_BUTTON_PENWI LD:WildDlg();break;}
Pen.DeleteObject();
Pen.CreatePen(PenStyle,MyPenWild,m_color);}
(14)编译运行,如图5.6.3和5.6.4所示。
图5.6.3画线和填充色、弹出调色板设置颜色
图5.6.4画笔宽度为20绘制的粗线
21
5.7多种图形的绘制
在实际工作中,经常要遇到绘制各种不同图形的情况,无论绘制什么图形,通常都需要创建画笔和画刷,然后调用CDC类中的绘图函数。
这些绘图函数包括画点、线、矩形、多边形、圆弧、椭圆、扇形、曲线等。
下面我们只通过3个实例,了解它们的绘制方法。
例5.10绘制2个不同填充形式的五角星(1)建一个单文档的应用程序,名为:五角星
(2)在视图类的实现文件(View.cpp)Draw函数中加下列代码:voidCMyView::OnDraw(CDC某pDC){
CMyDoc某pDoc=GetDocument();ASSERT_VALID(pDoc);
POINTpt[5]={{47,10},{30,90},{90,35},{10,30},{75,85}};//五角星的五个点CBruhbruh(HS_FDIAGONAL,RGB(255,0,0));//向上点斜线,红色CBruh某oldbruh=pDC->SelectObject(&bruh);pDC-
>SetPolyFillMode(ALTERNATE);pDC-
>Polygon(pt,5);for(inti=0;i<5;i++)pt[i].某+=80;//某+80第二个五星的点pDC->SetPolyFillMode(WINDING);
pDC->Polygon(pt,5);
pDC->SelectObject(oldbruh);bruh.DeleteObject();}
(3)编译运行,见图5.7.1所示。
图5.7.1绘制五角星及填充色
说明:
SetPolyFillMode(ALTERNATE):是CDC类的一个成员函数,用于设置
填充模式,它的参数可以是ALTERNATE和WINDING。
对於ALTERNATE方式,可以设想从一个无穷大的封闭区域内部的点画线,只有假想的线穿过了奇
数条边界线时,才填入封闭区域。
这就是填入了星的角而中心没被填入的
原因。
五角星的例子使得WINDING方式看起来比实际上更简单一些。
在绘
制单个的多边形时,大多数情况下,WINDING方式会填入所有封闭的区域。
但是也有例外。
在WINDING方式下要确定一个封闭区域是否被填入,仍旧
可以设想从那个无穷大的区域画线。
如果假想的线穿过了奇数条边界线,
区域就被填入,这和ALTERNATE方式一样。
如果假想的线穿过了偶数条边
界线,则区域可能被填入也可能不被填入。
如果一个方向的边界线数不相等,就填入区域。
例5.11绘制一条由点连起的曲线1、建一个单文档的应用程序,绘
曲线
2、在Viwe.cpp的OnDraw(CDC某pDC)函数里加如下代码:voidCMyView::OnDraw(CDC某pDC)
22
{CMyDoc某pDoc=GetDocument();ASSERT_VALID(pDoc);
intdata[20]={19,21,32,40,41,39,42,35,33,23,21,20,24,11,9,19, 22,32,40,42};CRectrc;
GetClientRect(rc);//是取得客户区矩形区域。