Windows 应用程序的图形设备接口(Graphics Device Interface,GDI)被抽象化为设备环 境(Device Context,DC)。设备环境又可称为设备描述表或设备文本,是 Windows 应用程序 与设备驱动程序和输出设备(显示器和打印机等)之间的连接桥梁。在 Windows 应用程序向 窗口用户区输出信息前,必须先获得一个设备环境对象,如果没有获得设备环境对象,则应用 程序和相应信息输出窗口之间就没有任何通道。
在 MFC 类库中, CDC 类是定义设备环境对象的类, 所有的绘图函数都在 CDC 类中定义,
因此,CDC 类是所有其他 MFC 设备环境的基类,任何类型的设备环境对象都可以调用这些绘 图函数。
要在 Windows 程序中输出图形或文字时,首先要调用该输出对象的设备环境,然后才运 行与之相对应的 CDC 类的成员函数进行绘图,屏幕画面的图形坐标系在缺省情况下,设屏幕 左上角的坐标值为(0,0),坐标系的逻辑单位为像素。最后要将设备环境释放给 Windows,恢复 原来的状态以备下次调用。
1.屏幕绘图的主要函数
CDC 类的主要绘图成员函数有以下 7 种。
(1)CDC::SetPixel 函数。执行该函数可以在屏幕画面上显示一个点。 其基本调用格式为:
pDC>SetPixel(x,y,RGB(0,0,255));
SetPixel()函数中的第 1、2 个参数为拟画点在屏幕上的显示坐标,第 3 个参数为拟画点颜 色的 COLORREF 型变量。该例句的执行结果是在屏幕画面的(x,y)处显示一个蓝点。
(2)CDC::MoveTo 函数和 CDC::LineTo 函数。执行这两个函数可以在屏幕画面上显示一 条直线,其基本调用格式为:
pDC>MoveTo(x1,y1);
pDC>LineTo(x2,y2);
由 MoveTo()函数确定直线的起始位置(x1,y1),再由 LineTo()函数指定直线的终点(x2,y2),
最后得到所要绘制的直线段。如果接着执行 LineTo()函数则可绘制出连续的折线段。该两例句 的执行结果是在屏幕画面坐标系中连接点(x1,y1)与点(x2,y2)绘制出一直线段。 绘制直线段的函 数不指定颜色,要改变线段的颜色可通过 GDI 的对象“笔”来实现。
(3)CDC::Ellipse 函数。执行该函数可以在屏幕画面上显示一个椭圆(或圆,圆是一种 长半轴和短半轴相等的椭圆,所以绘制圆和椭圆只要一个设备环境类的成员函数) 。其基本调 用格式为:
pDC>Ellipse(x1,y1,x2,y2);
Ellipse()函数用当前设备环境刷子填充椭圆内部并用当前设备环境笔画椭圆的边线,该函 数中的第 1 个参数是拟画椭圆的最左点横坐标,第 2 个参数是拟画椭圆的最上点纵坐标,第 3 个参数是拟画椭圆的最右点横坐标,第 4 个参数是拟画椭圆的最下点纵坐标。
(4)CDC::FillRect 函数。执行该函数可以在屏幕画面上显示一个矩形。其基本调用格 式为:
pDC>FillRect(CRect(point.x1,point.y1,point.x2,point.y2),&newBrush);
FillRect()函数用当前设备环境刷子填充矩形内部(不画边线)。该函数中的第 1 个参数 为拟画矩形的左上点和右下点的 CRect 类型参数 (其中的 4 个值分别为拟画矩形的左上点横
坐标和纵坐标、 右下点横坐标和纵坐标),第 2 个参数是为画此矩形所定义的刷子的对象(名 称)。
(5)CDC::Rectangle 函数。执行该函数可以在屏幕画面上显示一个矩形。其基本调用格 式为:
pDC>Rectangle(x1,y1,x2,y2);
Rectangle()函数用当前设备环境刷子填充矩形内部并用当前设备环境笔画矩形的边线。该 函数中的第 1 个参数和第 2 个参数分别是拟画矩形的左上点横坐标和纵坐标, 第 3 个参数和第 4 个参数分别是拟画矩形的右下点横坐标和纵坐标。
(6)CDC::Polygon 函数。执行该函数可以在屏幕画面上显示一个多边形,其基本调用格 式为:
pDC>Polygon(pt,5);
Polygon()函数用当前设备环境刷子填充多边形内部并用当前设备环境笔画多边形的边 线。该函数中的第 1 个参数为 CPoint 类对象的数组,第 2 个参数为数组的元素个数,此例句 中的 pt 即为 CPoint 的对象数组 pt[5]。该例句的执行结果是在屏幕画面上显示一个五边形,此 五 边 形 是 用 直 线 将 (pt[0].x,pt[0].y) 、 (pt[1].x,pt[1].y) 、 (pt[2].x,pt[2].y) 、 (pt[3].x,pt[3].y) 、 (pt[4].x,pt[4].y)等五个点首尾顺序连接而成的。
多边形的内部填充有两种模式:WINDING 和 ALTERNATE,缺省情况下为 ALTERNATE 模式。当填充模式设置为 WINDING 时,系统将填充整个多边形区域;当填充模式为 ALTERNATE 时 , 系 统 将 填 充 在 每 条 扫 描 线 奇 数 号 和 偶 数 号 多 边 形 之 间 的 区 域 。 调 用 CDC::SetPolyFillMode()函数可以对多边形进行填充模式的设置,其调用格式为:
pDC>SetPolyFillMode(WINDING);或 pDC>SetPolyFillMode(ALTERNATE);
(7) CDC::Arc 函数。 执行该函数可以在屏幕画面上显示一段圆弧线, 其基本调用格式为:
pDC>Arc((x0r),(y0+r),(x0+r),(y0r),x1,y1,x2,y2);
Arc()函数中的第 1、2 个参数和第 3、4 个参数分别为圆弧线所在圆的外切矩形的左上顶 点坐标((x0r),(y0+r))和右下顶点坐标((x0+r),(y0r)),第 5、6 个参数为圆弧线段起点坐标 (x1,y1),第 7、8 个参数为圆弧线段终点坐标(x2,y2)。如果把起点和终点取为同一个点,则画 出一封闭圆。
MM_LOMETRIC 0.1mm 逻辑坐标。坐标原点位置可自由设置,X 轴向向右,Y 轴向向上
MM_HIMETRIC 0.01mm 逻辑坐标。坐标原点位置可自由设置,X 轴向向右,Y 轴向向上
在默认情况下,设备环境使用 MM_TEXT 映射模式,该映射模式下的视图窗口坐标为设 备坐标,其坐标系原点在用户窗口的左上角点,X 轴向水平向右,Y 轴向垂直向下,基本单位 为一个像素,坐标值必须是正整数值。
以映射模式代码为参数,通过调用 CDC::SetMapMode()函数即可选定窗口屏幕的坐标系
(设定映射模式) 。映射模式设定后,GDI 内部的映射机制将把传给绘图函数的坐标值转换成 设备坐标值 (像素) , 从而在屏幕用户窗口区显示相应的图形。 通过调用 CDC::SetViewportOrg() 可以设定坐标系的原点位置。
设置一个屏幕逻辑坐标系的典型语句为:
CRect rect; //定义一个 CRect 类对象 rect GetClientRect(&rect); //得到一个视图窗口的矩形边界,
//其结果值保存在 CRect 对象 rect 中 pDC>SetMapMode(MM_LOMETRIC); //设定映射模式
pDC>SetViewportOrg(int(rect.right/2),int(rect.bottom/2));
//把逻辑坐标系的原点设在用户窗口的中心(点)
3.画笔的使用
Visual C++中的画笔用来绘制直线、曲线或填充图形的边线,是 Windows 图形设备接口
(Graphics Device Interface,GDI)对象之一。在使用 Visual C++的画笔之前必须先创建或选择 画笔对象, 使用 CPen 类的成员函数 CreatePen()可以创建一只笔, 而调用 CDC::SelectStockObject() 可以选择一只库笔。
创建一只笔的典型语句为:
CPen Mypen; //定义一个画笔对象 Mypen
CPen* poldPen; //定义一个 CPen 类对象指针 poldPen
Mypen.CreatePen(PS_SOLID,1,RGB(255,0,0)); //生成对应于 Mypen 的笔的 GDI 对象 poldPen=pDC>SelectObject(&Mypen); //把设备环境的笔调换成新生成的笔 Mypen,
//同时返回指向原设备环境的笔的指针 poldPen pDC>SelectObject(poldPen); //恢复原来的设备环境笔
Mypen.DeleteObject(); //把 Mypen 管理的笔的 GDI对象从系统内存中消除 4.刷子的使用
Visual C++中的刷子用来给图形内部着色,它也是 Windows 图形设备接口对象之一。在使 用 Visual C++ 的 刷 子 之 前 必 须 先 创 建 或 选 择 刷 子 对 象 。 使 用 CBrush 类 的 成 员 函 数 CreateSolidBrush()或 CreateHatchBrush()可以创建一只刷子,而调用 CDC::SelectStockObject() 可以选择一只库刷子。
创建一只刷子的典型语句为:
CBrush Mybrush; //定义一个刷子对象 Mybrush
CBrush* poldBrush; //定义一个 CBrush 类对象指针 poldBrush Mybrush.CreateSolidBrush(RGB(255,0,0)); //生成对应于 Mybrush 的刷子的 GDI 对象 poldBrush=pDC>SelectObject(&Mybrush); //把设备环境刷子调换成新刷子 Mybrush
//同时返回指向原设备环境刷子的指针 poldBrush pDC>SelectObject(poldBrush); //恢复原来的设备环境刷子
Mybrush.DeleteObject(); //把 Mybrush 管理的刷子的 GDI 对象从系统内存中消除 5.实例
下面的实例是在窗口中绘制一些常见的图形,通过该例介绍图形绘制的一般方法。
(1)建立 MyFigure 应用程序框架。
用应用程序向导建立单文档应用程序 MyFigure。
(2)添加 MFC 计算类头文件预编译指令。
在应用程序 MyFigure 的视图类实现文件 MyFigureView.cpp 的第 5 行之后添加 MFC 计算 类头文件 math.h 预编译指令。添加后 MyFigureView.cpp 文件的前 6 行局部形式为:
// MyFigureView.cpp : of the CMyFigureView 类的实现
#include "stdafx.h"
#include "MyFigure.h"
#include "MyFigureDoc.h"
#include "MyFigureView.h"
#include "math.h" //用户添加
(3)添加各图形绘制子函数的声明。
在应用程序 MyFigure 的视图类头文件 MyFigureView.h 中添加各绘图成员函数的声明, 完 成后的代码如下:
在应用程序 MyFigure 的视图类实现文件 MyFigureView.cpp 的最后写入各图形绘制子函数 的程序代码。
画矩形填充图形子函数(不画边界线) ,调用该子函数可以在指定位置显示一个指定大小 和颜色的矩形填充图形,程序代码如下:
void CMyFigureView::MyFillRect(CDC* pDC,COLORREF color,CPoint point,int length,int width) {//参数意义:刷子的颜色 color,矩形的左上点 point,矩形长度 length,矩形宽度 width CBrush my_brush(color); //定义刷子的一个对象,并对该对象初始化
CBrush* brush0; //定义一个 CBrush 类对象的指针 brush0 =pDC>SelectObject(&my_brush);
//把设备环境的刷子调换成新生成的刷子,同时返回指向原设备环境的刷子的指针 pDC>FillRect(CRect(point.x,point.y,point.x+length,point.y+width),&my_brush);
//用当前刷子画矩形,不画边线
pDC>SelectObject(brush0); //恢复原来的设备环境刷子 my_brush.DeleteObject(); //释放用户定义的刷子 }
画矩形填充图形子函数(画边界线) ,程序代码如下:
void CMyFigureView::MyRectangle(CDC* pDC,int x1,int y1,int x2,int y2,COLORREF color) {//参数意义:左上点(x1,y1),右下点(x2,y2),刷子的颜色 color
CBrush my_brush; //定义刷子的一个对象
CBrush* brush0; //定义一个 CBrush 类对象的指针 CPen* my_pen; //定义一个 CPen 类对象的指针 my_pen=(CPen*)pDC>SelectStockObject(NULL_PEN);
//在设备环境中分配一只透明库笔,同时返回指向原设备环境的笔的指针
//该透明笔用于画矩形的边线(不显示边线),缺省状态下系统将用黑笔画矩形边线 my_brush.CreateSolidBrush(color); //生成对应于 my_brush 的刷子的 GDI 对象
brush0=pDC>SelectObject(&my_brush);
//把设备环境的刷子调换成新生成的刷子,同时保存原设备环境的刷子的指针 pDC>Rectangle(x1,y1,x2,y2); //用当前刷子画矩形,用当前笔画边线 pDC>SelectObject(my_pen); //释放库笔,恢复原来的设备环境笔 pDC>SelectObject(brush0); //恢复原来的设备环境刷子
my_brush.DeleteObject(); //释放用户刷子 }
画实直线子函数,调用该子函数可以在指定位置显示一条指定粗细和颜色的直线段。程 序代码如下:
void CMyFigureView::MyLine(CDC* pDC,int x1,int y1,int x2,int y2,int line_width,COLORREF line_color)
{//参数意义:起点(x1,y1),终点(x2,y2),线宽 line_width,线色 line_color
CPen my_pen; //定义笔的一个对象
CPen* pen0; //定义一个 CPen 类对象的指针
my_pen.CreatePen(PS_SOLID,line_width,line_color);
//生成对应于 my_pen 的笔的 GDI 对象 pen0=pDC>SelectObject(&my_pen);
//把设备环境的笔调换成新生成的笔,同时返回指向原设备环境的笔的指针 pDC>MoveTo(x1,y1); //直线的起点
pDC>LineTo(x2,y2); //直线的终点
pDC>SelectObject(pen0); //恢复原来的设备环境笔 my_pen.DeleteObject(); //释放 my_pen
}
画圆填充图形子函数,用该子函数可以在指定位置显示一个指定半径和颜色的圆形填充
画圆填充图形子函数,用该子函数可以在指定位置显示一个指定半径和颜色的圆形填充