第5章 图形和文本输出
第5章 图形和文本输出 图形设备接口(GDI) CGdiObject对象 CDC 文本处理 绘图处理
图形设备接口 GDI(graphics device interface) 1.矢量图形 指画线和填充图形,包括点、直线、曲线、多边形、矩形等。 2.光栅图形 指光栅图形函数对以位图形式存储的数据进行操作,包括各种位图和图标的输出,在屏幕上表现为对若干行和列的像素操作。
图形设备接口 GDI(graphics device interface) 3.文本输出 是GDI的另一项任务,输出文本时对输出位置的计算不是以行为单位,而是以逻辑坐标为单位计算,用户可以设置文本的各种效果,如加粗、斜体、设置颜色等。 MFC处理图形输出类: 设备上下文CDC类 图形对象CGdiObject类
5.1.2 绘图工具GDI对象GdiObject CGdiObject是一个抽象类,该类不能直接定义对象。必须使用它的派生类
5.1.2 绘图工具GDI对象GdiObject GdiObject类是MFC提供绘图工具类。 各个派生类的任务如下: 1. 画笔(CPen) 封装GDI画笔,用于绘制对象的边框以及直线和曲线 2. 画刷(CBrush) 封装GDI画刷,用来填充一个封闭图形对象(如矩形、圆形)的内部区域。
5.1.2 绘图工具GDI对象GdiObject 3. 字体(CFont) 封装GDI字体,用户可以建立一种GDI字体,并使CFont的成员函数来访问它,主要用于设置文本输出的效果,字体大小、加粗、斜体、下划线等。 4. 位图(CBitmap) 提供成员函数装载和位图操作,位图可用于填充区域。
5.1.2 绘图工具GDI对象GdiObject 5.调色板(CPalette) 包含系统可用的色彩信息,是应用程序和彩色输出设备上下文的接口。 6. 区域(CRgn) 区域时窗口内的一块多边形或椭圆形区域。 CRgn类用于设备上下文内的区域操作。
5.1.3设备上下文DC device context DC是由GDI创建、用来代表设备连接的数据结构 DC主要功能: 1.允许应用程序使用一个输出设备 2.提供窗口应用程序,设备驱动,和输出设备之间的连接 3.保存当前信息,例如在一个窗口内绘图使用的颜色,画笔的宽度、画刷的类型等等 4.保存窗口剪取区域(clipping region),限制程序输出到输出设备中窗口覆盖的区域
设备上下文类-CDC CObject CDC CClientDC CMetaFileDC CPanitDC CWindowDC
设备上下文类-CDC MFC封装了DC,提供CDC类及它的子类以访问GDI。 各类操作如下: 1.CDC类
设备上下文类-CDC 2.CClientDC类 又名客户区设备上下文,用于客户区的输出,一般在响应非窗口消息并对客户区绘图时用到该类,例如:双击鼠标时输出文本等。 3.CpaintDC类 用于响应窗口重绘消息(WM_PAINT)的绘图输出,不仅可对客户区进行操作,还可对非客户区操作。
OnDraw函数 当用AppWizard创建单文档或多文档应用程序时,视图类包含成员函数OnDraw( )函数,CDC对象指针被传递给OnDraw( )函数。
OnDraw函数 void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->TextOut(1,1,”hello world!”); }
WM_PAINT消息 WM_PAINT消息是最重要的绘图消息,它要求窗口重新绘制内容,产生WM_PAINT消息的场合通常有: 窗口移动后及最大化,最小化后的刷新。 被覆盖区域的刷新,如下拉菜单覆盖的区域。 无效区域产生后的刷新,如执行滚动条操作,将一区域移动至不可见。
获取设备上下文 (DC) 绘图前必须准备好设备上下文(DC),获取设备上下文 的方法: 1.接受一个参数为指向CDC对象的指针 void CMyView::OnDraw(CDC* pDC); 2.构造CClientDC对象 CClientDC dc(this);
接受一个参数为指向CDC对象的指针 void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here //在坐标为10,10的位置上画一点,颜色黑色 pDC->SetPixel(CPoint(10,10),RGB(0,0,0)); } 参数为指向CDC对象的指针
构造CClientDC对象 { CClientDC dc(this); //this 指针将CMyView赋值给创建的dc对象 Void CMyView::OnLButtonDown(UNIT nFlags,CPoint point) { CClientDC dc(this); //this 指针将CMyView赋值给创建的dc对象 dc.SetPixel(point,RGB(255,0,0)); CView:: OnLButtonDown( nFlags,point); } 构造CClientDC对象
编程实例 例5-1 编写一个单文档MFC程序Exam5_1,在视图类增加成员变量,追踪鼠标左键双击位置的最新坐标,并输出坐标信息。
5.2 处理文本 设置文本颜色 设置文本显示属性 设置字体 格式化文本 文本输出函数
设置文本颜色 Windows操作系统中采用32位表示颜色,MFC和SDK采用COLORREF数据结构表示颜色,采用8位二进制数(0~255)分别表示红、蓝、绿3色 RGB宏是定义颜色最简单的方法,用3个参数,用0~255的值来表示颜色。
设置文本颜色 设置文本前景像素使用的颜色 COLORREF SetTextColor(COLORREF crColor); 设置文本背景像素使用的颜色 COLORREF SetBkColor(COLORREF crColor);
void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->SetTextColor(RGB(255,0,0)); pDC->SetBkColor(RGB(0,0,0)); CString str; str.Format("鼠标左键双击的位置是[%d,%d]", m_LPoint.x, m_LPoint.y); pDC->TextOut(0,0,str); }
设置字体 (Set Font) 设置显示字体的风格需要创建一个CFont对象,步骤如下: 1.定义CFont对象 2.调用CreateFont函数创建字体 3.将创建的字体对象选入DC,并保存前一个被选入DC的字体对象 程序举例Exam4:在视图中创建并使用字体,显示“倾斜的黑体”内容。
void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CFont NewFont; NewFont.CreateFont (65,65,0,0,FW_DONTCARE, true,false,false,DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "黑体"); CFont *pOldFont; pOldFont=pDC->SelectObject (&NewFont); pDC->TextOut(10,10,"字体效果"); }
格式化文本 文本测量函数 程序举例Exam5:在视图中输出使用两种颜色的一行文本 Hello Visual C++。 确定后继文本坐标:GetTextExtent()函 功能:获取字符串高度和宽度 程序举例Exam5:在视图中输出使用两种颜色的一行文本 Hello Visual C++。
文本输出函数 函数 说明 TextOut 在屏幕的固定位置用当前设定的颜色、字体、对齐方式输出文本 TabbedTextOut DrawText 在一个区域中显示并格式化文本 ExtTextOut 与TextOut的功能相似,但可以使用该函数删去超出矩形的正文,用正文背景填充矩形,调整字符间隔。
文本输出编程实例 例5-2 阅读单文档MFC(EXE)程序EXAM5_2中处理文本显示的OnDraw函数。请分析每一行的文本串作了哪些文本属性设置、格式设置和字体设置。
5.3 处理绘图 简单的图形输出 库存对象 设置绘图坐标系 创建和使用自定义画笔和画刷
5.3.1 简单的图形输出 CDC提供了基本的绘图操作函数,介绍如下: 1.画点 pDC->SetPixel(CPoint(200,200),RGB(255,0,0)); 在[200,200]的位置画一个红点 2.画线 pDC->MoveTo(0,0); //在视图的左上角一个X pDC->LineTo (100,100); pDC->MoveTo (0,100); pDC->LineTo (100,0);
3.画矩形 CRect rect(0,0,100,100); //画一个长100、宽100的矩形 pDC->Rectangle(&rect); 4.画圆和椭圆 CRect rect(0,0,100,100);//在矩形内画圆 pDC->Ellipse(&rect); CRect rect(0,0,50,100);//在矩形内画椭圆
5.画多边形 CPoint poly[4];//画一个平行四边形 poly[0]=CPoint(0,0); poly[1]=CPoint(50,50); poly[2]=CPoint(50,100); poly[3]=CPoint(0,50); pDC->Polygon(poly,4);
6.画其它图形 CDC::Pie 画饼图 CDC::Chord 画弦 CDC::FillRect 用指定颜色填充矩形且不画边线 CDC::Draw3DRect 用于绘制名种3D边框 CDC::RoundRect 画圆角矩形
5.3.2 库存对象 库存对象是由操作系统维护的用于绘制屏幕的常用对象 包括库存画笔,画刷,字体等 使用SelectStockObject可以方便直接选择库存对象,修改系统默认值 程序举例Exam6:在视图中选用画笔和画刷库存对象来画图
程序清单5-12 void CExam5View::OnDraw(CDC* pDC) { CExam5Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CRect rect; rect.SetRect (CPoint(0,0),CPoint(200,200)); pDC->SelectStockObject (WHITE_PEN); //选用白色画笔 pDC->SelectStockObject (GRAY_BRUSH);//选用灰色画刷 pDC->Rectangle (rect); pDC->MoveTo(0,0); pDC->LineTo (200,200); pDC->MoveTo (0,200); pDC->LineTo (200,0); }
5.3.3 设置绘图坐标系 如果要把一幅大小为400mm×800mm的图画在500像素×200像素的windows窗口中,我们把前者称为逻辑坐标,后者称为设备坐标。 原点 逻辑坐标 设备坐标 400mm 800mm 500像素 200像素 像素、厘米、毫米、英寸…
5.3.3 设置绘图坐标系 设备坐标系的原点总是在窗口的左上角,单位是像素。 逻辑坐标系的单位有多种,像素、厘米、毫米、英寸等。 逻辑坐标按映像模式分为三大类
映像模式 1.MM_TEXT 2.固定比例的映射模式 3.可变比例的映射模式 默认的映像模式,原点在左上角,向右x增加,向下y增加 允许改变比例因子和原点。在用户改变窗口大小时,绘制的内容会随之改变。如果改变一个轴的比例,则所绘的图像也会在其它轴上相应的改变。
修改映射模式 CClientDC dc; int OldMode=dc.SetMapMode(MM_LOMETRIC);
移动逻辑坐标系的原点 CRect rect; GetClientRect(rect); pDC->SetViewportOrg(rect.width()/2,rect.height()/2);
使用逻辑坐标和设备坐标的场合 MFC的CDC绘图函数都使用逻辑坐标为参数 CWnd的成员函数一般使用设备坐标为参数 返回鼠标位置作为屏幕位置测试时,一般使用设备坐标
设备坐标系统分类 1.工作区(Viewport)坐标系统 以窗口客户区左上角为原点(0,0),主要用于窗口客户区内的绘图输出以及处理窗口的一些消息。 2.窗口(Windows)坐标系统 以窗口左上角为原点(0,0),包含窗口控制菜单、标题栏等。 3.屏幕(Screen)坐标系统 以屏幕左上角为原点(0,0),当以CreateDC( )或GetDC( )函数创建或取得设备上下文用此坐标
设备坐标系统分类 MFC使用ClientToScreen和ScreenToClient两个函数,用于完成工作区坐标和屏幕坐标之间的转换工作。 CDC也提供了成员函数LPToDP和DPToLP完成两种坐标之间的转换。
创建自定义画笔 创建CPen的方法有两种: 1.定义时直接创建 CPen Mypen(PS_SOLID,2,RGB(255,0,0)); 2.定义CPen对象,再调用CreatePen( )函数 CPen pen; pen.Create(PS_SOLD, 2, RGB(255,0,0)) ;
创建自定义画刷 创建画刷有几种方法如下: 1.创建实心画刷 CBrush bs; bs.CreateSolidBrush(RGB(255,0,0)); //创建一个红色的实心画刷 2.创建阴影画刷 bs.CreateHatchBrush (HS_CROSS,RGB(255,0,0)); //创建一个十字线阴影的红色画刷
3.创建位图画刷(CreatePatternBrush) CBitMap bmp; bmp.LoadBitMap(IDB_MYBITMAP) CBrush bs bs.CreatePatternBrush(&bmp);
图形输出编程实例 例5-3使用和创建画笔和画刷。首先通过使用创建的蓝色,宽度为5的画笔画一个图形的边界,然后用当前的刷子填充这个图形来创建一个填充图形。共有三个填充图形:第一个是用深蓝色实心画刷填充的带圆角的矩形,第二个是用亮灰画刷填充的饼图,第三个是用阴影风格的画刷填充的椭圆。