----------------------- Page 1-----------------------
MFC
MFC
第一章 MMFFCC图形编程基础
1.1 MFC
1.1 MFC
11..11 MMFFCC概述
MFC(Microsoft Foundation Classes)库是Microsoft 为利用VC++开发
Windows 应用程序而提供的应用程序框架。在这个框架的支持下,对于不同的
应用程序,编程的主要任务是填写各自特殊部分的代码。MFC 类库由130 多个
类组成,封装了两千多个API函数。
使用MFC 编程具有很多优点:用类编程,将代码和数据封装在类中,大大
减少了编程的复杂性;通过继承实现了基本的代码重用,在开发应用程序的过程
中,我们可以通过继承来使用MFC 中已经定义了的大量类,在保有它们原有的
特性的同时,可以根据我们的需要来修改它们,使其具有新的特性;在使用MFC
进行编程的过程中,可以利用其提供的各种工具,提高编程的效率;借助MFC
类库中设计良好的类资源可以减少代码规模。使用MFC类库,编程者只需要注
意应用程序与通用的Windows 程序所不同的特性,而几乎所有的应用程序与
Windows之间的接口都是由应用程序框架来实现的,这大大降低了编程的难度。
Windows 区别于DOS 的一个重要的特征就是它的图形界面,所以,在
Windows的程序中绘图就成为了Windows 编程的一个非常重要的内容。为了满
足编程者在程序中绘图的需要,MFC 提供了许多与绘图相关的类和函数,使用
它们用户可以绘制出想要的各种图形。
1.2 MFC
1.2 MFC
11..22 创建MMFFCC项目
使用MFC 框架编程,首先需要创建一个MFC 项目,MFC的应用程序开发
都是在一个MFC 项目中完成的。在本教程中,我们使用的开发平台是Microsoft
Visual Studio 6.0 中的Visual C++ 6.0。
1.2.1 MFC AppWizard MFC
1.2.1 MFC AppWizard MFC
11..22..11 使用MMFFCC AAppppWWiizzaarrdd创建MMFFCC项目
在Microsoft Visual Studio 6.0 中,我们可以利用MFC AppWizard(MFC
应用程序向导)来建立MFC 项目,它提供了一个应用程序所必需的框架文件,
如源文件、头文件、资源文件、项目文件等等。创建MFC 项目由以下几个步骤
完成:
(1) 启动Visual C++ 6.0,如图1.1 所示。
(2) 从File 菜单中选择New 选项,出现New对话框(新建对话框),如
----------------------- Page 2-----------------------
图1.2 所示。该对话框包括Files、Projects、Workspace 和OtherDocuments
四个分页。选中Projects 分页,在Projects 面板中左侧的项目类型列表框中单
击选中要创建的项目类型。这里我们选
择 MFC AppWizard[exe]项,表示要创
建一个MFC 应用程序。在Project Name 文本输入框中输入要创建的项目的名
称。我们在这里输入项目名称为“DrawTest”,本章的演示程序将在该项目中来
完成。在Location 文本输入框中输入用户希望存放项目的目录名,用户也可以
点击输入框右侧的 按钮,调用“Choose Directory”对话框来选择目录。系
统会在用户选择的目录下创建一个与项目名称相同的目录来存放项目文件。系统
的默认目录是Microsoft Visual Studio 6.0 安装目录下的MyProjects 目录。下
面的一组单选按钮:Create new workspace,代表创建一个新的项目;Add to
current workspace,代表要加入到当前的项目中。这里我们选择创建一个新的
项目。因为Visual C++ 6.0 在32 位的操作系统平台上运行,所以在Platform
编辑框中必须选中Win32 复选框。
(3) 单击OK 按钮。出现MFC AppWizard – Step 1 对话框,如图1.3
所示。在这一步中,用户要选择应用程序的类型和资源文件所使用的语言。用户
可以创建基于Single document(单文档),Multiple document(多文档)和
----------------------- Page 3-----------------------
Dialogbased(对话框)的应用程序。这里我们选择创建基于单文档的应用程序。
在“What type of application would you like to create?”下拉框中,选择“中
文[中国]”作为资源文本语言。选中“Document/View architecture support”
复选框,表示应用程序将支持文档/视图体系。关于文档/视图体系,将在后面进
行介绍。
(4) 单击Next 按钮,出现MFC AppWizard – Step 2 of 6 对话框,
如图1.4 所示。在“What database support would you like to include?”中,
选择None单选钮,表示不需要数据库支持。
(5) 单击Next 按钮,出现MFC AppWizard – Step 3 of 6 对话框,
如图1.5 所示。在“What compound document support would you like to
include?”中,选择None单选钮,表示不需要复合文档的支持。同时在“What
other support would you like to include?”中,选择ActiveX Controls 复选框,
表示包括ActiveX。
----------------------- Page 4-----------------------
----------------------- Page 5-----------------------
----------------------- Page 6-----------------------
(6) 单击Next 按钮,出现MFC AppWizard – Step 4 of 6 对话框,
如图1.6 所示。在这一步,用户将对应用程序的界面特征进行设定。在“What
features would you like to include?”中,选中3D controls(三维图形控件)
选项,使控件具有立体感。如果用户选择了DockingTools 选项,那么“How do
you want your toolbars to look?”被激活,这里有
两个单选按钮:Normal 表
示生成传统意义上横跨在窗口顶端的工具条;Internet Explorer Rebars 表示生
成IE4 风格的附加工具条。选中Initialstatusbar复选框,表示窗口具有状态条。
选中Printing and print preview 复选框,表示应用程序提供打印和打印预览。
在“How many files would you like on your recent filelist?”中使用默认值4,
表示生成的应用程序的File 菜单中显示4 个最近打开过的文件。
(7) 单击Next 按钮,出现MFC AppWizard – Step 5 of 6 对话框,
如图1.7 所示。在“What style of project would you like?”有两个单选按钮:
MFC Standard 表示提供一个标准的MFC 应用程序架构;Windows Explorer
----------------------- Page 7-----------------------
表示建立一个像Windows Explorer 那样使用分割窗口的应用程序,左边的成列
窗口是CTreeView类,右边的成列窗口是CListView类。在“Would you like to
generate source file comments?”中,选择Yes, Please,表示在源代码中加
上注释。在“How wouldyou like touse theMFC library?”中,选择As a shared
DLL,表示使用动态链接库,当应用程序仅使用MFC 类库时,动态链接有利于
减少占用的磁盘空间。
----------------------- Page 8-----------------------
(8) 单击Next 按钮,出现MFC AppWizard – Step 6 of 6 对话框,
如图1.8 所示。在这里可以修改所创建的类的类名和文件名,修改应用程序视类
的基类。在列表框中单击选择CDrawTestView 类,可以单击Base class 下拉
框的箭头,从中选择要使用的基类。我们这里使用默认的CView作为基类。除
了修改应用程序视类的基类外,我们不建议修改这里各个类的类名和文件名。
(9) 单击Finish 按钮,出现New Project Information对话框,如图1.9
所示。这里将显示用户前面几步所做的所有设置。如果检查设置无误,可以单击
OK 按钮,完成MFC 项目的创建,系统在指定的目录下生成了应用程序的框架
文件。
----------------------- Page 9-----------------------
至此,MFC 项目创建完毕。实际上我们在第(3)步之后各步的设置中采用
的都是系统的默认选项,所以可以在第(3)步选择完单文档应用程序后,直接
单击Finish 按钮,这时将直接出现第(9)步的New Project Information 对话
框,这里表示第(3)步之后的各项设置都采用系统的默认设置。在第(3)步
之后的各步中随时可以选择Finish 按钮来直接完成设置。
MFC
1.2.2 MFC
1.2.2 MMFFCC
11..22..22 项目工作区窗口
MFC 创建完成之后,用户可以通过项目工作区窗口进行文件组织,项目管
理和项目设置更改
。如图1.10 所示。
----------------------- Page 10-----------------------
在项目工作区窗口中一共有三个分页,分别是 ClassView 面板、
ResourceView面板和FileView面板。在每个面板中都有一个树型结构,用户可
以用鼠标单击树型节点左侧的“+”字展开节点或者单击“-”字层叠节点。
(1) ClassView面板(类面板)
类面板显示了当前项目中所包含的类和类成员的树型结构,如图1.11 所示。
展开“DrawTest classes”节点,该节点的下层节点就是当前项目中所包含
的所有类;展开每个类节点,所显示的就是该类中的所有类成员,包括成员函数
和成员变量。在类的每个成员节点的左边都有一个小图标,该图标给出了成员函
数或成员变量的类型以及存取类别:
钥匙图标,表示该类成员为保护成员;
红色方块,表示该类成员为成员函数;
蓝色方块,表示该类成员为成员变量;
锁,表示该类成员为私有成员变量;
“Globals”节点下是项目中的全局成员。
通过使用类面板,用户可以很方便的查看和编辑源代码文件。双击类节点,
就会打开对应该类的头文件;双击类成员节点,就会打开相应的源码文件,并定
位到相应的位置:双击成员函数,打开类文件(.cpp文件),并定位到函数方法
名最左端;双击成员变量,打开头文件(.h文件),并定位到变量声明的最左端。
----------------------- Page 11-----------------------
如图1.12,就是双击了CDrawTestView类的OnDraw(CDC *pDC)成员函数节
点。开发平台打开DrawTestView.cpp 类文件,并将光标定位在OnDraw 函数名
的最左端。用户可以在源代码编辑窗口中进行代码编写。
在类节点或类成员节点上用鼠标右键单击,会弹出快捷菜单,如图1.13 所
示。利用快捷菜单,用户可以方便的创建新类;给已有类增减成员函数和成员变
量;直接跳转到类、成员函数、成员变量的定义和声明处等等。具体的使用方法
将在后面进行介绍。
----------------------- Page 12-----------------------
(2)ResourceView面板(资源面板)
资源面板用于管理项目资源,应用程序中所使用的对话框、图标、菜单、工
具条等都属于项目资源。
----------------------- Page 13-----------------------
如图1.14 所示。根节点“DrawTest resources”的下层节点是各种项目资
源文件夹。展开项目资源文件夹,就可以看到项目中包含的资源。双击资源节点,
就可以对该资源进行查看和编辑。例如用户想要查看当前应用程序的工具条,就
可以先展开Toolbar 项目文件夹节点
,然后双击IDR_MAINFRAME(我们所创
建的应用程序的工具条),就可以对该工具条进行查看和编辑。
(3)FileView面板(文件面板)
文件面板显示了项目所包含的各种文件及其之间的关系,如图1.15 所示。
----------------------- Page 14-----------------------
用鼠标双击文件面板中的文件名,源代码编辑窗口会自动以合适的编辑器打
开相应的文件。在文件面板中我们看到在“Source Files”中有一个DrawTest.rc
文件。.rc 文件就是项目的资源文件,双击该文件,将自动打开资源面板。
虽然我们在文件面板中也可以打开类的源代码文件,对类及其成员进行编
辑。但是这里还是强烈建议用户使用类面板对类及其成员进行操作。在面向对象
程序设计中,程序员操作的对象是类,代码的设计和编写始终都应该是基于类对
象的。通过类面板,用户可以时刻了解当前应用程序的类组成,而且每个类的成
员构成一目了然。尽管VisualC++ 6.0 中每个类仍然是由两个源代码文件组成,
但是我们在编程过程中应该将这两个文件当成一个整体来看。利用类面板及其提
供的快捷菜单,也可以加快开发,减少错误。
1.2.3 /
1.2.3 /
11..22..33 文档//视图体系
前面在创建MFC 项目的时候,我们曾经设置过要应用程序支持文档/视图
体系。这里我们说明一下什么是文档/视图体系。
在说明之前,先看看我们创建的这个单文档应用程序都包含了哪些类。通过
类面板,我们可以看到在当前项目中包含了五个类:CAboutDlg 类,
CDrawTestApp 类,CDrawTestDoc 类,CDrawTestView 类和CMainFrame 类。
----------------------- Page 15-----------------------
其中CAboutDlg 类是一个对话框类,其基类是CDialog。该类是应用程序中的
“关于”对话框。运行应用程序,我们可以看到该对话框,这里不详细说明了。
CDrawTestApp CWinApp CWinApp
类是应用程序对象类,其基类是 。 类是每个
Windows 应用程序对象的基类,它完成应用程序的初始化、运行和终止功能。
所以CDrawTestApp类在整个应用程序中完成程序初始化、运行及终止的工作。
CMainFrame CFrameWnd CFrameWnd
类是主框架窗口类,其基类是 。 类是单
文档应用程序主框架窗口的基类。在应用程序中,工具条和状态条都属于主框架
窗口,所以它们都在该类中进行加载。还有两个类,就是我们要介绍的文档和视
图。CDrawTestDoc 类是文档类,其基类是文
档基类 CDocument 。
CDrawTestView类是视图类,在本项目中,选择的基类是视图基类CView。
MFC应用程序通过建立文档/视图体系,将数据、数据的显示和用户对数据
的操作区分开来,使多视图、多文档类型、拆分窗口等有用的功能特性更加容易
实现。在文档/视图体系中,数据被移植到文档(Document)数据对象中,输出
功能由视图承担,而框架窗口仅仅是一个容器,负责包含和管理视图。
文档(Document)就是数据对象的集合。通过它,用户可以定义、存储和
管理应用程序的数据,并可以将数据写入或读出永久存储介质(如硬盘等)。
视图(View)就是窗口对象,负责向输出设备(如显示屏幕、打印机等)
输出应用程序中的数据(在本书中主要是向显示屏幕输出图形数据),提供文档
和用户的交互界面。通过它,可以观察、选择和编辑文档中的数据,所有用户和
文档的交互都必须通过与文档相对应的视图进行。MFC 中的绘图基本就是在视
图中进行绘图。
文档和视图是一个不可分割的统一体!文档基类CDocument 和视图基类
CView 是文档/视图体系中最重要的两个类。所有的文档类都是由CDocument
派生而来的。CDocument 包容了用户应用程序中的数据,定义了框架窗口如何
对文档起作用。CView 类及其派生视图类是用户的数据窗口,它控制着应用程
序文档内容的显示以及用户和应用程序文档的交互(MFC 的绘图及相关的用户
交互都是在视图中完成的)。不同的视图派生类分别支持不同的功能。如
CSrollView类是具有滚动功能的视图类,从它派生的类可以自动实现滚动功能;
CFormView类是对话框资源视图类,从它派生的类可快速实现基于对话框资源
的用户界面;CEditView 类为文档提供一个基于文本编辑的用户界面;
CDaoRecordView类提供直接链接到DAO 记录集的表单视图;CRichEditView
类比CEditView 类封装了更多的文本编辑功能,如支持字体、颜色、段落格式
化等等;CListView类是列表控件视图类,用于显示图标和字符串;CTreeView
类是树形图视图类,等等。
1.3 DC OnDraw
1.3 DC OnDraw
11..33 设备环境DDCC和OOnnDDrraaww函数
通过前面的介绍,我们已经创建了一个MFC 项目DrawTest,并且了解了
MFC 的文档/视图体系,知道MFC 绘图绝大多数都是在视图中绘图。而在视图
中绘图必须使用设备环境DC。现在我们先完成一个简单的在视图中的绘图。
----------------------- Page 16-----------------------
通过类面板,选择CDrawTestView 类的OnDraw方法。在OnDraw方法中
的“// TODO
: add draw code for native data here”注释下输入代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->LineTo(200,200);//用户编写的代码
}
然后编译运行应用程序。这里简单介绍一下Visual C++ 6.0 的Build 工具
条。如图1.16 所示。
工具条中的各按钮功能如下表:
图 标 命 令 功 能
Compile 编译文件
Build 建立项目
Stop Build 停止项目的建立
Execute Program 执行文件
Go 启动或继续执行程序
Insert Remove Breakpoint
/ 插入/删除断点
我们可以先用Compile 或者Build 来编译链接应用程序,然后用Execute
Program来运行应用程序。因为MFC项目涉及的类较多,有时候因为编译顺序
问题,在使用Compile 命令时会出错,实际此时程序不一定有错误,所以建议
使用Build命令来进行编译和链接。我们也可以直接运行程序,如果此时程序创
建或更改后没有进行编译,系统会先询问是否需要编译。如果选择“是”,则系
----------------------- Page 17-----------------------
统会重新编译链接应用程序并运行;选择“否”,如果程序以前编译过,则运行
以前编译过的程序;也可以选择“取消”来撤销这次程序运行。在程序中设置了
Go
断点,需要进行跟踪时使用 命令,用来继续执行程序。
运行我们编写完OnDraw 方法的应用程序,得到结果如图1.17 所示。我们
看到在应用程序窗口的视图区部分(应用程序窗口中间的白色部分)绘制了一条
直线。我们所编写的OnDraw 函数是在视图内绘图最常用的函数。该函数是
CView 类中的一个虚函数,每次当视图需要重新绘制时,应用程序框架都会自
动调用该函数(关于视图重画将在后面详细介绍),例如用户改变了窗口的大小,
或者窗口恢复先前被覆盖的部分时。在系统自动生成的OnDraw 函数中已有两
行代码:
CDrawTestDoc* pDoc = GetDocument();//获得与视图对应的文档类的
指针
ASSERT_VALID(pDoc);//检查该指针是否为空
OnDraw 函数传入的参数是CDC 类对象指针,这里的CDC 类就是设备环
境类的基类。我们编写的代码:
pDC->LineTo(200,200);
就是调用了CDC 的成员函数LineTo来绘制了一条直线。
函数LineTo可以
称为绘图函数。
DC Device Context
设备环境 ( ,又称设备上下文或设备描述表)是一个关
----------------------- Page 18-----------------------
于如何绘制图形的方法的集合。它可以绘制各种图形,也可以确定在应用窗口中
绘制图形的方式,即确定绘图模式和映射模式。在MFC中包含了一些设备环境
类,CDC 是设备环境类基类,还有从其派生的一些设备环境类。基类CDC包含
了绘图所需要的所有成员函数,而且除了CMetaFileDC 派生类之外,其他所有
的派生类都只有构造函数和析构函数的定义有所不同。这些设备环境派生类的目
的是为了在不同的显示设备上进行显示。CDC 类的派生类有CClientDC 类,
CPaintDC 类,CMetaFileDC 类和CWindowDC 类。用显示屏幕进行显示常用
CClientDC CWindowDC CDC
的派生类是 和 。下表列出 类派生类的功能简介:
派生类名称 说 明
CClientDC 提供对窗口视图区域的图形绘制,在窗口中绘图时可以
使用此类DC,但对WM_PAINT Windows 消息除外
CPaintDC 响应WM_PAINT Windows 消息的设备环境类,可以
使用此DC 更新Windows 显示,通常在MFC 应用程
序中的OnPaint()函数中使用
CWindowDC 提供在整个窗口(包括视图区和非视图区)中进行绘图
的DC
CMetaFileDC 代表Windows 元文件。想要创建独立于设备的文件时
DC
可以使用此类 ,用户可以回放这种文件来创建图像
CWindowDC CPaintDC CClientDC CPaintDC
类和 及 类的区别一方面是用
类和CClientDC 类的对象绘制图形时,绘制区只能是视图区,而不能是非视图
区,而CWindowDC 可以在非视图区进行绘图。如图1.17 所示的应用程序窗口
中,中间的白色部分都属于视图区(直线就绘制在视图区中),而窗口标题、菜
单栏,工具条和状态条都属于非视图区。CWindowDC 一般在框架窗口类
(CMainFrame)中引用。在视图窗口中引用CWindowDC 类时,因为视图类只
能管理视图区,所以并不能在非视图区进行绘图。它们之间的另一个区别是:在
CWindowDC设备环境类下,坐标系是建立在整个屏幕上的,在像素坐标方式下,
坐标原点在屏幕的左上角;而在CPaintDC 和CClientDC 下,坐标系是建立在
视图区的,在像素坐标方式下
,坐标原点在视图区的左上角。
CPaintDC 和CClientDC 的区别在于它们的绘制机制。CPaintDC 应用在
OnPaint 函数中,响应Windows 的WM_PAINT 消息,而CClientDC 应用在非
响应WM_PAINT消息的情况下。所以我们在视图中进行绘图的时候一般都采用
CClientDC,而CPaintDC一般只在OnPaint函数中使用。
DC
用户在绘图之前,必须获取绘图窗口区域的一个设备环境 ,接着才能够
调用其绘图函数进行绘图。因为在OnDraw 函数中,系统已经自动传入了一个
设备环境类指针,用户可以直接通过该指针调用绘图函数进行绘图。如果要在视
DC
图类的其它函数中进行绘图就必须首先获取设备环境 ,常用的获取方法有以
下几种:
(1) 如果要绘制图形的函数由OnDraw函数调用,则可以将OnDraw函
数中的CDC对象指针作为该函数的一个参数传入;
(2) 可以构造CClientDC对象,使用该对象进行绘图,其构造函数为
----------------------- Page 19-----------------------
CWnd*
CWnd*
CClientDC(CCWWnndd** pWnd)
因为CView类由CWnd类(所有窗口的基类)派生而来,所以构造的时候
传入当前视图类的指针即可。
(3) 可以通过GetDC()函数来获得设备环境对象指针,其原型声明如下:
CDC* CWnd::GetDC()
该函数没有任何参数,用于获取一个窗口视图区指针。调用的时候通过当前
视图类指针进行调用。
下面举例来说明如何通过上面三种方法来获得设备环境对象。
首先在CDrawTestView 类中添加一个函数,用鼠标右键单击类面板中的
CDrawTestView类节点,在弹出的快捷菜单中选择“AddMemberFunction…”,
出现增加成员函数对话框,如图1.18 所示。
在Functio Type(函数返回类型)文本输入框中输入void,表示函数没有
返回值。在Function Declaration(函数声明)文本输入框中输入Draw(CDC
*pDC),表示创建一个名称为Draw 的函数,参数为CDC 类指针。在Access
中可以选择Public(公有),Protected(保护)或者Private(私有),我们选择
Public,表示Draw 函数是一个公有函数。下面的复选框为Static(静态函数)
Virtual OK CDrawTestView
和 (虚函数)。然后点击 按钮,系统自动在 类中添
加Draw 函数,并在源代码编辑窗口中定位到该函数处,同时在头文件中添加
Draw函数的声明。建议用户使用这种方法来增加类的成员函数,在减少工作量
的同时可以
避免写了函数体之后忘记在头文件中进行声明的问题。同时,尽管
Visual C++ 6.0 允许写不属于任何类的函数,在调用上也没有问题,但是我们
仍然建议不要写这种函数,因为它与面向对象程序设计的思想不符。另外,因为
不属于类的函数无法通过类面板看到,如果这样的函数多的话,会让程序员不清
----------------------- Page 20-----------------------
楚自己的应用程序项目中都有哪些函数,更容易出错。
在我们新增的Draw函数中输入如下代码。为了举例,该函数中三种获得设
备环境对象的方法都使用了,在实际应用中,使用其中一种即可。
void CDrawTestView::Draw(CDC *pDC)
{
pDC->LineTo(200,100);//使用传入的CDC对象指针绘图
CClientDC dc(this);//构造CClientDC设备环境对象
dc.LineTo(200,200);//利用构造的CClientDC设备环境对象绘图
CDC* p=this->GetDC();//通过GetDC函数获得设备环境对象指针
p->LineTo(100,200);//利用GetDC函数获得设备环境对象指针绘图
this->ReleaseDC(p);//由 GetDC 函数获得的设备环境对象必须用
ReleaseDC函数释放
}
修改OnDraw函数,在OnDraw函数中调用Draw 函数。
void CDrawTestView::OnDraw(CDC* pDC)
----------------------- Page 21-----------------------
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
Draw(pDC);//调用Draw函数
}
运行应用程序,结果如图1.19 所示。从运行结果可以看出,三种方法获得
的设备环境对象都可以进行绘图。在实际应用中可以根据需要进行选择。如果要
进行绘图的函数是通过OnDraw 函数进行调用的,建议采用第一种方法;而在
该函数不通过OnDraw函数调用的时候使用另外两种方法。
1.4 CDC
1.4 CDC
11..44 CCDDCC类常用绘图函数
在获得设备环境对象后,具体的绘图工作是由绘图函数完成的, CDC 类提
供了一些基本的绘图函数供用户使用,如果进行复杂绘图的话,就需要通过算法
来组织这些基本绘图函数来完成绘图。本节介绍一下这些基本绘图函数。
1.4.1 SetPixel GetPixel
1.4.1 SetPixel GetPixel
11..44..11 SSeettPPiixxeell函数和GGeettPPiixxeell函数
SetPixel
SetPixel
SSeettPPiixxeell函数用于绘制一个点,其函数声明如下:
COLORREF SetPixel(int x, int y, COLORREF crColor);
COLORREF SetPixel(POINT point, COLORREF crColor);
x y point
参数 和 是逻辑坐标系下要绘制的点的
坐标,参数 也是用于指定要
绘制的点的坐标。结构体POINT是用于定义逻辑坐标下一个点的坐标位置的,
其结构定义如下:
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT;
参数crColor 指定了要绘制的点的颜色,其类型是COLORREF,即32 位
的颜色单位,定义这个颜色最简单的方法是使用RGB 函数:
----------------------- Page 22-----------------------
COLORREF RGB(BYTE bRed, BYTE bGreen, BYTE bBlue);
bRed bGreen bBlue
其中的 , 和 参数分别代表红、绿、蓝三色的相对密度,
每个参数的取值范围是0-255,0 代表没有该颜色分量,255 代表最大。函数
返回实际绘制点的颜色值。
GetPixel
GetPixel
GGeettPPiixxeell函数用于获得指定点的颜色,其函数声明如下:
COLORREF GetPixel(int x, int y);
COLORREF GetPixel(POINT point);
参数意义与SetPixel相同。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
for (int i=0;i<255;i=i+5)
{
//绘制一系列红颜色程度不同的点
pDC->SetPixel(i+10,100,RGB(i,0,0));
}
for (int j=0;j<255;j=j+5)
{
//用与要绘制的点对应的点的颜色来绘制
pDC->SetPixel(j+10,200,pDC->GetPixel(j+10,100));
}
}
----------------------- Page 23-----------------------
运行程序,结果如图1.20 所示。
程序先绘制一系列红颜色分量从0 开始变化的点,然后再分别获得这些点
的颜色值,绘制了一系列新的点。因为SetPixel 函数只能绘制大小为一个像素
的点,所以效果看起来不是非常明显。
LineTo MoveTo
1.4.2 LineTo MoveTo
1.4.2 LLiinneeTToo MMoovveeTToo
11..44..22 函数和 函数
LineTo
LineTo
LLiinneeTToo函数用于绘制一条从当前绘图位置到指定坐标点的直线段,其函
数声明如下:
BOOL LineTo(int x, int y);
BOOL LineTo(POINT point);
x y point
参数 和 ,及参数 指定了坐标点。这里我们注意到,一条直线段应
该有两个端点,可是这里只指定了一个点。这是因为在使用设备环境对象进行绘
图的时候有一个当前绘图位置的概念,该位置是逻辑坐标系下的一个坐标点。
LineTo 函数是在当前绘图位置和
指定的点之间绘制一条直线段。初始的当前绘
图位置是视图区逻辑坐标系的原点,该原点在默认的映射模式下是在视图区的左
上角。所以在我们的第一个例子中,绘制了一条从视图区左上角到(200, 200)
点的直线段(如图1.17 所示)。LineTo 函数在绘制完直线段后,将当前绘图位置
----------------------- Page 24-----------------------
移到参数所指定的新的坐标点处。如果画直线段成功,函数返回TRUE,否则返
回FALSE。
MoveTo
MoveTo
MMoovveeTToo函数用于将当前绘图位置移到指定的坐标点处,函数声明如下:
CPoint MoveTo(int x, int y);
CPoint MoveTo(POINT point);
x y point CPoint
参数 和 ,及参数 指定了新的当前绘图位置坐标。返回值是
对象实例,它包含了新的当前绘图位置坐标。CPoint 类是MFC中定义的一个点
x y int
对象的类,它有两个成员变量 和 ,用于存放点的坐标位置,类型为 。在绘
图函数参数中所有使用POINT结构的地方都可以使用CPoint类。MoveTo 函数
通常与LineTo函数同时使用,来绘制一条指定了端点的直线段。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->MoveTo(10,10);
POINT p1;p1.x = 100;p1.y = 100;//使用POINT结构
pDC->LineTo(p1);
CPoint p2;p2.x = 200;p2.y = 100;//使用CPoint类
pDC->LineTo(p2);
}
运行程序,结果如图1.21 所示。
----------------------- Page 25-----------------------
程序先把当前绘图位置移到(10, 10)点,然后绘制了从(10, 10)点到(100,
100)点的直线段。此时当前绘图位置移到了(100, 100)点,所以下一个LineTo
函数绘制了(100, 100)点到(200, 100)点的直线段。程序中两个画线函数分
别使用了POINT 结构和CPoint 类作为函数的参数。其中,CPoint 类有构造函
数CPoint(int x, int y),我们可以使用该构造函数直接构造CPoint对象作为绘
图函数的参数。OnDraw 函数中最后两行代码可以用此代码代替:
pDC->LineTo(CPoint(200, 100));。
需要注意的是:当前绘图位置是针对设备环境对象的,不同的设备环境对象
的当前绘图位置并不互相影响。修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//
TODO: add draw code for native data here
CDC* pDC2=this->GetDC();//获得另一个设备环境对象
pDC->LineTo(100,100);
----------------------- Page 26-----------------------
pDC2->LineTo(200,100);
pDC->LineTo(300,200);
pDC2->LineTo(300,200);
}
运行程序,结果如图1.22 所示。
程序中获得了另一个设备环境对象pDC2。用pDC 绘制了从原点到(100,
100)点的直线段后,pDC 的当前绘图位置移到了(100, 100)点。而对于pDC2
来说,当前绘图位置并没有变化,仍然是默认的原点,所以 pDC2 绘制了从原
点到(200, 100)点的直线段,此时pDC2 的当前绘图位置移到了(200, 100)
点。所以后面pDC绘制了从(100, 100)点到(300, 200)点的直线段,而pDC2
绘制了从(200, 100)点到(300, 200)点的直线段。
----------------------- Page 27-----------------------
1.4.3 Polyline PolylineTo
1.4.3 Polyline PolylineTo
11..44..33 PPoollyylliinnee函数和PPoollyylliinneeTToo函数
Polyline
Polyline
PPoollyylliinnee函数用于绘制一条由一系列指定的点连接而成的折线,其函数
声明如下:
BOOL Polyline(LPPOINT lpPoints, int nCount);
参数lpPoints 指向POINT 结构或者CPoint 对象数组,该数组按顺序存放
折线连接点的坐标,而nCount 是连接点的个数,该参数必须要大于1。如果画
线成功,函数返回TRUE;否则返回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
POINT p[5];
p[0].x = 10;p[0].y = 10;
p[1].x = 100;p[1].y = 100;
p[2].x = 200;p[2].y = 100;
p[3].x = 200;p[3].y = 200;
p[4].x = 100;p[4].y = 50;
pDC->Polyline(p,5);
}
运行程序,结果如图1.23 所示。
----------------------- Page 28-----------------------
PolylineTo
PolylineTo
PPoollyylliinneeTToo函数也用于绘制折线,其函数声明如下:
BOOL PolylineTo(const POINT* lpPoints, int nCount);
该函数参数意义与Polyline 函数相同。PolylineTo 与Polyline 有两点区别:
一是PolylineTo 函数绘制的折线的起始点并不是输入的点数组中的第一个点,
而是当前绘图位置;二是Polyline 函数执行完毕后,将当前绘图位置移动到所绘
制折线的最后一点处。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//
TODO: add draw code for native data here
CPoint p[5];
p[0].x = 10;p[0].y = 10;
p[1].x = 100;p[1].y = 100;
p[2].x = 200;p[2].y = 100;
----------------------- Page 29-----------------------
p[3].x = 200;p[3].y = 200;
p[4].x = 100;p[4].y = 50;
pDC->PolylineTo(p,5);
pDC->LineTo(300,100);
}
运行程序,结果如图1.24(1)所示。然后将PolylineTo函数改成Polyline
函数,再次运行程序,结果如图1.24(2)所示。
从运行结果可以看出,PolylineTo函数绘制的折线起始点在原点(左上角),
因为在默认情况下,设备环境的当前绘图位置是原点。如果想用PolylineTo 函
数绘制出与Polyline 函数所绘制的折线相同的折线,就需要在执行PolylineTo
之前把当前绘图位置移动到点数组的第一个点。在本程序中就需要在
pDC->PolylineTO(p, 5)代码之前加上pDC->MoveTo(10, 10)。PolylineTo 函
数执行完后,将当前绘图位置移动到了折线的最后一点,所以后面的画线函数绘
制的是(100, 50)到(300, 100)的直线段。而Polyline 函数并不改变当前绘图
位置,所以绘制的是从默认当前绘图位置到(300, 100)的直线段。
Arc ArcTo
1.4.4 Arc ArcTo
1.4.4 AArrcc AArrccTToo
11..44..44 函数和 函数
Arc
Arc
AArrcc函数用于绘制一个椭圆形的弧线,它是一个指定的矩形的内切椭圆
----------------------- Page 30-----------------------
的一段。所绘制弧线的实际起点是该内切椭圆与一条直线的交点,而该直线是从
椭圆中心到指定点的连线。弧线的实际终点也是如此。如图1.25 所示:
函数声明如下:
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);
第一个函数参数给出了四对坐标:第一对坐标是要绘制的圆弧所在椭圆的外
接矩形的左上角坐标;第二对坐标是要绘制的圆弧所在椭圆的外接矩形的右下角
坐标;第三对坐标指定了圆弧的起点;第四对坐标指定了圆弧的终点。在画圆弧
时,默认的圆弧方向是逆时针,即圆弧是按逆时针方向从起点到终点的。第二个
函数给出的参数中,后两个使用POINT结构来存放起点和终点坐标。而第一个
参数LPCRECT是指向MFC 中定义矩形区域的数据结构的指针,该矩形区域结
构定义如下:
typedef struct tagRECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT;
left top right bottom x
其中 , , ,
分别代表矩形区域的左上角的 坐标,左上
y x y RECT
角的 坐标,右下角的 坐标,右下角的 坐标。我们可以使用 来定一
个结构体做为函数的参数,也可以使用MFC中定义的用于存放矩形区域坐标的
----------------------- Page 31-----------------------
类CRect,该类也具有RECT 结构的四个参数。在使用RECT 结构的地方也可
以使用CRect 类,其关系与POINT 结构和CPoint 类的关系相同。当函数绘图
成功,返回TRUE,否则返回FALSE。
ArcTo
ArcTo
AArrccTToo函数也用于绘制一个椭圆形的弧线。它与Arc 函数的区别类似于
Polyline 函数与PolylineTo函数的区别。ArcTo 函数绘制弧线后将当前绘图位置
移动到终止点,并且该函数起始绘图位置并不是设定的起始点,而是当前绘图位
置。其函数声明如下:
BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL ArcTo(LPCRECT plRect, POINT ptStart, POINT ptEnd);
Arc
函数参数的含义与 函数相同。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->Arc(100,100,300,300,100,150,250,150);
CRect r;
r.left = 350;r.top = 100;
r.right = 650;r.bottom = 300;
POINT p1,p2;
p1.x = 500;p1.y = 100;
p2.x = 650;p2.y = 150;
pDC->MoveTo(p1);
pDC->ArcTo(r,p1,p2);
}
运行程序,结果如图1.26 所示:
----------------------- Page 32-----------------------
Arc ArcTo ArcTo
该段程序分别用 函数和 函数绘制了两个椭圆形弧线。在用
绘制弧线之前,先将当前绘图位置移动到了 p1 点处。如果将此句代码去掉,程
序将绘制一条从默认当前绘图位置原点到p1 点的直线段,读者可以自行试验一
下。
1.4.5 AngleArc
1.4.5 AngleArc
11..44..55 AAnngglleeAArrcc函数
AngleArc
AngleArc
AAnngglleeAArrcc函数用于绘制一条直线段和一段圆弧线。它在当前绘图位置
和圆弧的起点之间绘制一条直线段,并根据给定的圆的圆心坐标,半径,和起始
和终止角度绘制一个圆弧。其函数声明如下:
BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float
fSweepAngle);
该函数的前两个参数定义了圆心的位置;第三个参数是圆的
半径;第四和第
x
五个参数分别定义了要绘制的圆弧相对于 轴的起始角和终止角,该参数值为角
度值。如果绘图成功函数返回TRUE,否则返回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
----------------------- Page 33-----------------------
// TODO: add draw code for native data here
pDC->MoveTo(100,100);
pDC->AngleArc(200,200,50,90,270);
}
运行程序,结果如图1.27 所示:
该段程序先将当前绘图位置移动到(100, 100)点。所绘制圆弧所在圆的圆
心为(200, 200),半径为50,起始角为90 度,终止角为270 度。在当前绘
x
图位置与由起始角所确定的圆弧的起始点之间绘制了一条直线段。这里 轴正向
为0 度,绘制圆弧方向为逆时针方向。
PolyBezier PolyBezierTo
1.4.6 PolyBezier PolyBezierTo
1.4.6 PPoollyyBBeezziieerr PPoollyyBBeezziieerrTToo
11..44..66 函数和 函数
PolyBezier
PolyBezier
PPoollyyBBeezziieerr函数用于绘制一条Bezier 参数曲线,其函数声明如下:
BOOL PolyBezier(const POINT* lpPoints, int nCount);
----------------------- Page 34-----------------------
其中参数lpPoints 与Polyline 函数中相同,指向POINT 结构或者CPoint
对象数组,在数组中存放的是Bezier 参数曲线的控制点。nCount 是控制点的个
数。关于Bezier 参数曲线的知识后面将会详细的介绍,这里只简单说明一下该
函数的参数要求:首先控制点的个数要求是3n+1 个,其中n是Bezier 参数曲线
的段数,比如要绘制两段Bezier参数曲线,控制点的个数应为7,其中第1 到第
4 的四个点控制第一段曲线,第4 到第7 的四个点控制第二段曲线。当要绘制
的曲线是两段或者两段以上时,为了保证曲线各段之间光滑连接,要求相接的两
段曲线连接处的三个控制点要共线,如曲线是由两段构成时,控制点数为7,那
么要求第3、第4 和第5 个点三点共线。如果绘图成功,函数返回TRUE,否
则返回FALSE。
PolyBezierTo
PolyBezierTo
PPoollyyBBeezziieerrTToo函数也用于绘制Bezier 参数曲线。其函数声明如下:
BOOL PolyBezierTo(const POINT* lpPoints, int nCount);
其参数含义与PolyBezier 函数相同。该函数与PolyBezier 函数的区别是:
PolyBezierTo函数默认第一个控制点为当前绘图位置,所以PolyBezier 函数的
控制点个数
要求是3n 个;PolyBezierTo 函数绘制完曲线后,将当前绘图位置移
动到最后一个控制点处。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
POINT p[7];
p[0].x = 200;p[0].y = 100;
p[1].x = 200;p[1].y = 200;
p[2].x = 300;p[2].y = 200;
p[3].x = 400;p[3].y = 300;
----------------------- Page 35-----------------------
p[4].x = 500;p[4].y = 400;
p[5].x = 300;p[5].y = 400;
p[6].x = 100;p[6].y = 450;
pDC->PolyBezier(p,7);
}
运行程序,结果如图1.28 所示。
再修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
POINT p[6];
pDC->MoveTo(200,100);
p[0].x = 200;p[0].y = 200;
p[1].x = 300;p[1].y = 200;
p[2].x = 400;p[2].y = 300;
p[3].x = 500;p[3].y = 400;
p[4].x = 300;p[4].y = 400;
p[5].x = 100;p[5].y = 450;
pDC->PolyBezierTo(p,6);
}
运行程序,其结果与1.28 所示相同。
----------------------- Page 36-----------------------
两段程序分别使用 PolyBezier 函数和 PolyBezierTo 函数绘制了相同的
Bezier曲线,我们从代码上可以很容易看出两个函数的差别。
Rectangle
1.4.7 Rectangle
1.4.7 RReeccttaannggllee
11..44..77 函数
Rectangle
Rectangle
RReeccttaannggllee函数用于绘制矩形,其函数声明如下:
BOOL Rectangle(int x1, int y1, int x2, int y2);
BOOL Rectangle(LPCRECT lpRect);
其中第一个函数参数给出了两组点坐标,第一组为矩形的左上角点坐标,第
二组为矩形的右下角点坐标。第二个函数使用了指向矩形区域结构的指针作为参
数,也可以使用CRect 类。如果绘图成功,函数返回TRUE,否则返回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
----------------------- Page 37-----------------------
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->Rectangle(50,50,200,80);
CRect r;
r.left = 100;r.right=200;
r.top = 100;r.bottom = 200;
pDC->Rectangle(r);
}
运行程序,结果如图1.29 所示:
RoundRect
1.4.8 RoundRect
1.4.8 RRoouunnddRReecctt
11..44..88 函数
RoundRect
RoundRect
RRoouunnddRReecctt函数用于绘制圆角矩形,即四个角被椭圆化的矩形。如果将
----------------------- Page 38-----------------------
圆角矩形的四个圆角移动到一起,就可以拼成一个完整的椭圆。其函数声明如下:
BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3);
BOOL RoundRect(LPCRECT lpRect, POINT point);
其中,第一个函数的参数x1 和y1 指定了矩形的左上角点坐标,参数x2 和
y2 指定了矩形的右下角点坐标,参数x3 指定了用来绘制圆角的椭圆的宽度,参
数y3 指定了用来绘制圆角的椭圆的高度。如图1.30 所示。第二个函数用矩形
POINT x
区域结构来存放矩形的左上角和右下角坐标,用 结构的 来存放圆角椭
y TRUE
圆的宽度, 来存放圆角椭圆的高度。如果绘图成功,函数返回 ,否则返
回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->RoundRect(50,50,200,80,10,10);
CRect r;
----------------------- Page 39-----------------------
r.left = 100;
r.right=200;
r.top = 100;
r.bottom = 200;
POINT p;
p.x = 50;
p.y = 30;
pDC->RoundRect(r,p);
}
运行程序,结果如图1.31 所示。
1.4.9 Ellipse
1.4.9 Ellipse
11..44..99 EElllliippssee函数
Ellipse
Ellipse
EElllliippssee函数用于绘制椭圆或者圆,其函数声明如下:
BOOL Ellipse(int x1, int y1, int x2, int y2);
BOOL Ellipse(LPCRECT lpRect);
其中,第一个函数的参数x1 和y1 指定了要绘制的椭圆或者圆的外接矩形的
左上角点坐标,参数x2 和y2 指定了要绘制的椭圆或者圆的外接矩形的右下角
点坐标。第二个函数的参数使用了矩形区域结构来存放外接矩形的左上角和右下
角坐标。如果绘图成功,函数返回TRUE,否则返回FALSE。
修改OnDraw函数,输入如下代码:
----------------------- Page 40-----------------------
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
----------------------- Page 41-----------------------
// TODO: add draw code for native data here
pDC->Ellipse(50,50,200,80);
CRect r;
r.left = 100;
r.right=200
;
r.top = 100;
r.bottom = 200;
pDC->Ellipse(r);
}
运行程序,结果如图1.32 所示。
因为程序中CRect 类对象 定义的是一个正方形区域,所以r Ellipse 函数绘
制的是一个圆。
1.4.10Pie
1.4.10Pie
11..44..1100PPiiee函数
Pie
Pie
PPiiee函数用于绘制扇形,它是由椭圆弧与其起始点和终止点所对应的椭
圆的半径所围成的图形,其函数声明如下:
BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
Arc Arc Pie
其参数含义与 函数相同,差别在于 函数只绘制了椭圆弧,而 函
数将椭圆弧所确定的扇形绘制出来。如果绘图成功,函数返回TRUE,否则返回
FALSE。
----------------------- Page 42-----------------------
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->Pie(100,100,300,300,100,150,250,150);
}
运行程序,结果如图1.33 所示。
Arc
程序中使用的参数值与 函数示例中的参数值相同,通过对比两个函数的
运行结果,就可以知道两个函数的差别。
Chord
1.4.11 Chord
1.4.11 CChhoorrdd
11..44..1111 函数
Chord
Chord
CChhoorrdd函数用于绘制一个椭圆与一条直线相交所得到的图形,其函数声
----------------------- Page 43-----------------------
明如下:
BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
Arc Pie Chord
其参数含义与 函数和 函数相同,差别在于 函数绘制的是指
定的起始点和终止点所在的直线与椭圆相交所得到的图形。如果绘图成功,函数
返回TRUE,否则返回FALSE。
我们仍然采用Arc 函数和Pie 函数示例时所使用的参数值,修改OnDraw
函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->Chord(100,100,300,300,100,150,250,150);
----------------------- Page 44-----------------------
}
运行程序,结果如图1.34 所示。
Arc
Pie Chord
对比运行结果,我们可以看出, 函数、 函数和 函数都是由给
Arc Pie
定的参数决定了一段椭圆弧,差别在于 函数只绘制了该段椭圆弧, 函数
绘制了该段椭圆弧所对应的扇形,而Chord 函数则在椭圆弧的起始点和终止点
之间用直线段连接。
1.4.12Polygon
1.4.12Polygon
11..44..1122PPoollyyggoonn函数
Polygon
Polygon
PPoollyyggoonn函数用于绘制一个封闭的多边形,其函数声明如下:
BOOL Polygon(LPPOINT lpPoints, int nCount);
参数lpPoints 存放的是多边形的顶点坐标,nCount 是多边形的顶点数目,
该参数必须大于2。如果绘图成功,函数返回TRUE,否则返回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
POINT p[5];
p[0].x = 10;p[0].y = 10;
p[1].x = 100;p[1].y = 100;
p[2].x = 200;p[2].y = 100;
p[3].x = 200;p[3].y = 200;
p[4].x = 100;p[4].y = 50;
pDC->Polygon(p,5);
}
运行程序,结果如图1.35 所示:
----------------------- Page 45-----------------------
PolyPolygon
1.4.13PolyPolygon
1.4.13PPoollyyPPoollyyggoonn
11..44..1133 函数
PolyPolygon
PolyPolygon
PPoollyyPPoollyyggoonn函数用于绘制多个多边形,其函数声明如下:
BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int
nCount);
其中,参数lpPoints 存放了所有多边形的顶点,参数lpPolyCounts 指向一
个整数的数组,该数组中的每一个数定义了相应的多边形的顶点的数量,参数
nCount 则定义了所要绘制的多边形的数量,它的值必须大于等于2。如果绘图
成功,函数返回TRUE,否则返回FALSE。
修改OnDraw函数,输入如下代码:
void CDrawTestView::OnDraw(CDC* pDC)
{
CDrawTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
POINT p[6];
p[0].x = 10;p[0].y = 10;
p[1].x = 100;p[1].y = 100;
p[2].x = 200;p[2].y = 100;
----------------------- Page 46-----------------------
p[3].x = 200;p[3].y = 200;
p[4].x = 100;p[4].y = 50;
p[5].x = 150;p[5].y = 20;
int d[2];
d[0] = 3;d[1] = 3;
pDC->PolyPolygon(p,d,2);
}
运行程序,结果如图1.3