计算机图形学简单的画图工具.doc_第1页
计算机图形学简单的画图工具.doc_第2页
计算机图形学简单的画图工具.doc_第3页
计算机图形学简单的画图工具.doc_第4页
计算机图形学简单的画图工具.doc_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

北京联合大学实验(实习、实训)报告课程(项目)名称: 实用计算机图形学实训 学 院: 师范学院 专 业:计算机科学与技术班 级: 学 号: 姓 名: 成 绩: 年月日图形软件开发一、任务与目的 实验任务为在理解直线、圆、方、区域填充等的基础上,进行小型图形应用软件的开发。综合运用所学过的知识掌握小型图形软件的绘制。软件的主要功能包括图形的绘制,颜色的设置和保存等功能。本软件具有使用性、稳定性、易用性,和可维护性的特点,用户可以根据需要对其功能进行填充、完善与修改,使其符合自己的要求。2、 原理(条件)2.1、所用的软件VC+6.0 是 Microsoft 公司推出的一个基于 Windows 系统平台、可视化的 集成开发环境,它的源程序按 C+语言的要求编写,并加入了微软提供的功能 强大的 MFC(Microsoft Foundation Class)类库。MFC 中封装了大部分 Windows API 函数和 Windows 控件,它包含的功能涉及到整个 Windows 操作系统。MFC 不仅给用户提供了 Windows 图形环境下应用程序的框架, 而且还提供了创建应 用程序的组件,这样,开发人员不必从头设计创建和管理一个标准 Windows 应 用程序所需的程序,而是从一个比较高的起点编程,故节省了大量的时间。另 外,它提供了大量的代码,指导用户编程时实现某些技术和功能。因此,使用VC+提供的高度可视化的应用程序开发工具和 MFC 类库,可使应用程序开发变 得简单。MFC(Microsoft Foundation Classes) ,是 一 个 微 软 公 司 提 供 的 类 库 ( class libraries)以 C+类的形式封装了 Windows 的 API, , 它包含了窗口等许多类的定义。各种类的集合构成了一个应运程序的框架结构,以减少应用程序开发人员的工作 量。其中包含的类包含大量 Windows 句柄封装类和很多 Windows 的内建控件和组 件的封装类。MFC 6.0 版本封装了大约 200 个类,其中的一些可以被用户直接使用。例如CWnd 类封装了窗口的功能,包括打印文本、绘制图形及跟踪鼠标指针的移动等;CsplitterWnd 类是从 CWnd 类派生出来的,继承了基类或称父类 CWnd 类的所 有特 性,但增加了自己的功能,实现拆分窗口,使窗口至少可被拆分成两个窗口,用户 可以移动两个窗口之间的边框来改变窗口的大小;CtoolBar 类可以定义工具栏等。MFC 命名的惯例是类的名字通常是由“C”打头;成员变量使用前缀“m_”,接着使用一个字母来指明数据类型,然后是变量的名称;所有的单词用大写字母开头。 2.2、CDC类CDC 是设备环境类的基类直接由 CObject 派生。是 GDI 的关键元素,它代表了物理设备。每一个 C+设备环境对象都有相对应 Windows 设备环境,并通过一个 32 位类型的 HDC 句柄来标识。CDC 类的虚拟性使我们可以很容易的做到编写同时适用 于多种设备的代码。 使用 CDC 类可以使我们的作图不用关心设备的问题。CClientDC 和 CWindowDC 是显示设备环境类,都是由 CDC 派生而来,区别在于 CClientDC 是窗 口的客户区不包括边框、 标题栏和菜单栏, (0, 指客户区域的左上角。 0) CWindowDC 的(0,0)指整个屏幕的左上角,这意味着我们可以在显示器的任意地方绘图,包 括窗口边框、标题栏和菜单栏等等。在编写鼠标绘图的代码之前,首先要确定如何用鼠标完成绘图。以用鼠标绘制直线段为例:首先将鼠标的光标移动到直线段的一个端点处,按下鼠标左键,然后按住鼠标左键不放,移动鼠标光标到直线段的另一个端点处,此时松开鼠标左键,就完成了用鼠标绘制直线段,应用程序会在两个端点之间绘制一条直线段。绘制椭圆和椭圆区域比较类似,先后确定的是椭圆的外接矩形的两个对角点。而对于绘制矩形区域,则确定的是矩形区域的两个对角点。2.3、Bresenham算法Bresenham算法1965年提出,基本原理是:借助于一个误差量(直线与当前实际绘制像素点的距离),来确定下一个像素点的位置。算法的巧妙之处在于采用增量计算,使得对于每一列,只要检查误差量的符号,就可以确定该下一列的像素位置。2.4、鼠标为了在应用程序中响应用户的鼠标动作,就需要在编写应用程序时选择响应鼠标消息并编写其对应的处理函数。针对用户使用鼠标的一些基本操作,比如鼠标的单击、双击、移动等,Windows提供了相应的通用消息。这些鼠标消息按照鼠标动作发生的区域可以分为两大类:视图区鼠标消息和非视图区鼠标消息。非视图区鼠标消息指鼠标光标在应用程序窗口视图区外的非视图区发生动作时产生的鼠标消息。非视图区包括标题栏、最小化和最大化按钮、关闭窗口按钮、系统菜单栏和窗口框架等。非视图区鼠标消息虽然用得比较少,但对于应用程序窗口的管理是有用的。通过非视图区鼠标消息可以知道窗口何时进行移动、关闭或改变大小。下表中列出了常用的非视图区鼠标消息及其含义:非视图区鼠标消息含义WM_NCMOUSEMOVE非视图区鼠标移动WM_NCLBUTTONUP非视图区鼠标左键抬起WM_NCLBUTTONDBLCLK非视图区鼠标左键双击WM_NCLBUTTONDOWN非视图区鼠标左键按下WM_NCRBUTTONUP非视图区鼠标右键抬起WM_NCRBUTTONDBLCLK非视图区鼠标右键双击WM_NCRBUTTONDOWN非视图区鼠标右键按下视图区鼠标消息指鼠标光标在应用程序窗口视图区内发生动作时产生的鼠标消息。视图区鼠标消息比较常用,用鼠标绘图就要使用视图区鼠标消息。下表列出了常用的视图区鼠标消息及其含义:视图区鼠标消息含义WM_MOUSEMOVE视图区鼠标移动WM_LBUTTONUP视图区鼠标左键抬起WM_LBUTTONDBLCLK视图区鼠标左键双击WM_LBUTTONDOWN视图区鼠标左键按下WM_RBUTTONUP视图区鼠标右键抬起WM_RBUTTONDBLCLK视图区鼠标右键双击WM_RBUTTONDOWN视图区鼠标右键按下实现对鼠标消息的处理要完成以下工作:(1) 定义鼠标消息处理函数;(2) 使用消息映像宏实现鼠标消息和消息处理函数间的消息映像;(3) 编写鼠标消息处理函数的代码。下表列出了视图区鼠标消息对应的消息映像宏及消息处理函数:视图区鼠标消息消息映像宏消息处理函数WM_MOUSEMOVEON_WM_MOUSEMOVE()afx_msg void OnMouseMove (UINT nFlags, CPoint point);WM_LBUTTONUPON_WM_LBUTTONUP()afx_msg void OnLButtonUP (UINT nFlags, CPoint point);WM_LBUTTONDBLCLKON_WM_LBUTTONDBLCLK()afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point);WM_LBUTTONDOWNON_WM_LBUTTONDOWN()afx_msg void OnLButtonDown (UINT nFlags, CPoint point);WM_RBUTTONUPON_WM_RBUTTONUP()afx_msg void OnRButtonUp (UINT nFlags, CPoint point);WM_RBUTTONDBLCLKON_WM_RBUTTONDBLCLK()afx_msg void OnRButtonDblClk (UINT nFlags, CPoint point);WM_RBUTTONDOWNON_WM_RBUTTONDOWN()afx_msg void OnRButtonDown (UINT nFlags, CPoint point);其中消息处理函数的参数point是CPoint对象,它存储了产生鼠标消息时鼠标光标所处位置的坐标,如鼠标左键按下的处理函数中传入的point参数中存放了鼠标左键按下位置的坐标。参数nFlags是一个无符号数,它表明了在鼠标消息产生的时候鼠标按钮及部分键盘按键的状态,其值可为下表中值的任意组合:nFlags参数值说明MK_CONTROLCtrl键按下MK_LBUTTON鼠标左键按下MK_MBUTTON鼠标中键按下MK_RBUTTON鼠标右键按下MK_SHIFTShift键按下u SetCapture函数,用于捕捉鼠标,其函数声明如下:CWnd* SetCapture();该函数是窗口基类CWnd的成员函数,因为CView类是从CWnd类派生而来的,所以它也拥有该函数。该函数返回捕捉了鼠标的窗口指针。执行该函数后,视图类就捕捉了鼠标,此后的鼠标动作都将产生视图区鼠标消息。u ReleaseCapture函数,用于释放鼠标,其函数声明如下:BOOL ReleaseCapture();该函数用于释放被捕捉的鼠标。在用鼠标绘图完毕后,需要调用该函数释放鼠标,否则窗口将不能正确接受鼠标消息。除了在鼠标绘图开始时捕捉鼠标之外,也可以通过调用ClipCursor函数将鼠标限制在指定区域中以避免在鼠标绘图过程中出现不同类型的鼠标消息。u ClipCursor函数,用于将鼠标限制在指定的矩形区域中,其函数声明如下:BOOL ClipCursor(CONST RECT lpRect);参数lpRect指向一个RECT结构体,该结构体定义了一个矩形区域,该函数将鼠标限制在此矩形区域中。如果鼠标光标要移动到矩形区域外,系统将自动调正鼠标光标位置,使其始终在指定的矩形区域内。通常用如下代码把鼠标限制在应用程序窗口的视图区内:CRect rect;/矩形区域对象GetClientRect(&rect);/获得并保存窗口视图区区域坐标ClientToScreen(&rect);/用视图区区域坐标重新计算屏幕坐标ClipCursor(&rect);/限制鼠标在窗口视图区中上面的代码将鼠标限制在窗口的视图区中,这样鼠标只能在视图区中产生动作,也就只会产生视图区鼠标消息。其中用到的GetClientRect函数和ClientToScreen函数都是CWnd类的成员函数。u GetClientRect函数,用于获得窗口视图区的矩形区域坐标,其函数声明如下:void GetClientRect(LPRECT lpRect) const;该函数将窗口的视图区的左上角和右下角坐标存放在lpRect指针指向的矩形区域结构中。u ClientToScreen函数,用于将传入的矩形区域坐标或点坐标转化成实际的屏幕坐标,其函数声明如下:void ClientToScreen(LPPOINT lpPoint) const;void ClientToScreen(LPRECT lpRect) const;参数lpPoint和lpRect分别指向点结构和矩形区域结构,该函数将传入的点的坐标或矩形区域的坐标(左上角点和右下角点坐标)转换成实际的屏幕坐标,这样调用ClipCursor函数时才能将鼠标限制在正确的区域中。被限制的鼠标在绘图完毕后应该取消限制,采用如下语句来完成取消对鼠标的限制:ClipCursor(NULL);限制鼠标移动范围会加大系统负担,所以通常不采用此种方法。在用鼠标绘制图形时,我们希望修改鼠标光标形状,而不是使用默认的斜箭头光标。鼠标的光标形状由专门的光标(Cursor)资源所决定。我们可以在资源面板上向项目中添加光标资源(在添加资源对话框中有光标资源类型,如图2.3所示),每个光标资源对应一个唯一的资源ID,应用程序框架通过该ID来识别光标资源。要使用光标资源作为鼠标的光标形状,需要首先将光标资源加载到系统中,然后再设置鼠标光标形状为加载的光标资源的形状。u LoadCursor函数,用于加载光标资源,其函数声明如下:HCURSOR LoadCursor(LPCTSTR lpszResourceName) const;HCURSOR LoadCursor(UINT nIDResource) const;参数lpszResourceName和nIDResouce分别为光标资源的名称和ID号,函数将指定的光标资源加载到系统内存中。函数返回光标资源句柄(HCURSOR)。u LoadStandardCursor函数,用于加载Windows预定义的光标资源,其函数声明如下:HCURSOR LoadStandardCursor(LPCTSTR lpszCursorName) const;参数lpszCursorName是由一些以IDC_开头的光标资源名称,用来指定Windows预定义的光标资源,下表中列出了预定义的光标资源名称和对应的光标形状:预定义的光标资源名称光标形状IDC_ARROW标准的斜箭头光标IDC_IBEAM标准的插入文本光标IDC_WAIT沙漏形状的光标IDC_CROSS标准的十字光标IDC_UPARROW向上方向的箭头IDC_SIZEALL带有四个方向箭头的光标IDC_SIZENSWE带有左上和右下方向箭头的光标IDC_SIZENESW带有右上和左下方向箭头的光标IDC_SIZEWE带有左右方向箭头的光标IDC_SIZENS带有上下方向箭头的光标该函数同样返回光标资源句柄。上面两个加载光标资源的函数都是应用程序基类CWinApp的成员函数,在视图类中要使用该函数,需要调用AfxGetApp()函数获得应用程序基类的指针,然后再调用加载光标资源函数。加载完光标资源后,调用SetCursor函数设置使用光标资源。2.5、SetROP2Windows API SetROP2(int nDrawMode)主要用于设定当前前景色的混合模式。R2_NOT就是取反的意思,即前景色为背景色的反色,经常用R2_NOT来画橡皮线,因为两次取反可以还原背景色。根据nDrawMode设置的方式重新设定绘图的方式,下面就不同的nDrawMode值具体解释绘图模式是如何改变的。 首先就nDrawMode的取值有以下的情况: 1、R2_BLACKPixel is always black. /所有绘制出来的像素为黑色 2、R2_WHITEPixel is always white. /所有绘制出来的像素为白色 3、R2_NOPPixel remains unchanged. /任何绘制将不改变当前的状态 4、R2_NOTPixel is the inverse of the screen color. /当前绘制的像素值设为屏幕像素值的反,这样可以覆盖掉上次的绘图,(自动擦除上次绘制的图形) 5、R2_COPYPENPixel is the pen color. /使用当前的画笔的颜色 6、R2_NOTCOPYPENPixel is the inverse of the pen color. /当前画笔的反色 /下面是当前画笔的颜色和屏幕色的组合运算得到的绘图模式。 7、R2_MERGEPENNOTPixel is a combination of the pen color and the inverse of the screen color (final pixel = (NOT screen pixel) OR pen). /R2_COPYPEN和R2_NOT的并集 8、R2_MASKPENNOTPixel is a combination of the colors common to both the pen and the inverse of the screen (final pixel = (NOT screen pixel) AND pen). /R2_COPYPEN和R2_NOT的交集 9、R2_MERGENOTPENPixel is a combination of the screen color and the inverse of the pen color (final pixel = (NOT pen) OR screen pixel). /R2_NOTCOPYPEN和屏幕像素值的并集 10、R2_MASKNOTPENPixel is a combination of the colors common to both the screen and the inverse of the pen (final pixel = (NOT pen) AND screen pixel). /R2_NOTCOPYPEN和屏幕像素值的交集 11、R2_MERGEPENPixel is a combination of the pen color and the screen color (final pixel = pen OR screen pixel). /R2_COPYPEN和屏幕像素值的并集 12、R2_NOTMERGEPENPixel is the inverse of the R2_MERGEPEN color (final pixel = NOT(pen OR screen pixel). /R2_MERGEPEN的反色 13、R2_MASKPENPixel is a combination of the colors common to both the pen and the screen (final pixel = pen AND screen pixel). /R2_COPYPEN和屏幕像素值的交集 14、R2_NOTMASKPENPixel is the inverse of the R2_MASKPEN color (final pixel = NOT(pen AND screen pixel). /R2_MASKPEN的反色 15、R2_XORPENPixel is a combination of the colors that are in the pen or in the screen, but not in both (final pixel = pen XOR screen pixel). /R2_COPYPEN和屏幕像素值的异或 16、R2_NOTXORPENPixel is the inverse of the R2_XORPEN color (final pixel = NOT(pen XOR screen pixel). /R2_XORPEN的反色 总之,上述api的一个作用是在需要改变绘图的模式时,不需要重新设置画笔,只需要设置不同的绘图的模式即可达到相应的目的。3、 内容与步骤3.1工程的新建 打开 Microsoft Visual C+ 6.0 点击 File New 在 Projects 中选择 MFC AppWizard (exe) ; 在 Project name 中输入工程的名字 Graphic,在 Location 中选 择工程存放的路径。填完后点击 OK 按钮。(如图 1)填完后点击 OK 按钮,弹出对话 框(如图 2)。在弹出来的对话框中我们可以选择生成三种不同类型的应用程序:单 文档、多文档、对话框。 单文档程序如记事本,在一个应用程序中只能对一个文档进行操作,降低了编 程的复杂度并减少了运行程序时所需的资源。对某些小型应用(比如文本编辑器或 小型图像编辑器)可以采用这种类型的窗口应用程序。 多文档程序如 PhotoShop,在一个应用程序中可以同时对多个文档进行操作; 对话框程序如 QQ,应用程序的界面是对话框形式的。现对话框版本的程序更小一 些。除了节省资源外,对话框版本的应用程序的加载速度也更快些。基于对话框的 应用程序比完成相同功能的基于窗口的应用程序更简单有效。 这里我们选第一个:单文档。 选择完后点击 Next,设置默认,最后点击 Finish 完成工程的创建。图1图23.2单文档生成单文档程序后,进行编译,在运行,我们可以看到以下的结果。如图 3图3在 ClassView 中,我们可以看到系统自动为我们生成了五个类:CApp , CDoc , CView , CAboutDlg , CMainFrame。 如图 4图4CApp相当于C语言中的main()函数。是程序的起始。 CDoc是用于处理程序中文档的类。 CView主要是处理客户区的可视化的操作的类。 CAboutDlg是处理关于对话框的类。 CMainFrame是非客户区的一些资源的类。 我们主要是对CView类进行操作。3.3 详细设计首先,在Toolbar中建立新的工具条IDR_DRAW。如图5图5在新建的工具条中建立如图6所示图标,并分别命名为ID_DRAWLINE、ID_DRAWZHILINE、ID_DRAWELLIPSE、ID_DRAWFANG、ID_DRAWELLIPSESHI,ID_DRAWFANGSHI、ID_XIANGPI、ID_DRAWFILL、ID_DRAWRED、ID_DRAWBLACK、ID_DRAWG、ID_Color。分别是画笔、直线、椭圆、长方形、实心椭圆、实心方、橡皮、种子填充、红色、黑色、绿色、颜色。图6新的工具条创建完毕,此时如果我们运行应用程序,会发现该工具条并没有显示出来,这是因为我们还没有编写代码将该工具条加入到应用程序窗口中。下面我们来看一下如何将工具条加入到应用程序窗口中。首先,选择类面板,双击CMainFrame节点,在右侧的编辑区中将打开CMainFrame类的头文件。这里声明了一个CStatusBar类对象变量m_wndStatusBar和一个CToolBar类对象变量m_wndToolBar。它们分别对应了系统自动添加的默认状态栏和默认的初始工具条。然后,该对象将用于与绘图工具条对应。在类面板中双击CMainFrame节点下的OnCreate节点,在编辑区打开CMainFrame类的CPP文件,并定位到该类的OnCreate成员函数处。该成员函数在主窗口创建的时候调用,在此函数中可以给主窗口添加工具条和状态栏。再次添加如下代码:/创建绘图工具条if (!m_DrawToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) |!m_DrawToolBar.LoadToolBar(IDR_DRAW)TRACE0(Failed to create toolbarn);return -1; / fail to create/设置绘图工具条的停放状态m_DrawToolBar.EnableDocking(CBRS_ALIGN_ANY);/在主窗口中放置绘图工具条DockControlBar(&m_DrawToolBar);添加了如上代码之后,我们就将刚才新建的工具条加入到了主窗口中,运行应用程序,我们将在默认的初始工具条下面看到我们新添加的绘图工具条。该工具条与初始工具条一样,可以移动位置,并可以停放在窗口的四个边框中的任意一边上。但是此时该工具条中的按钮都处于不可用状态,这是因为还没有为工具条按钮连接处理函数。如图7图73.3.1 点、直线、矩形、椭圆、矩形区域、椭圆区域的绘制为了实现绘制的成功,需要添加CP2、CCircle、CLine与CRGB类。在绘图的过程中要使用点的横左边、纵坐标与点的颜色,所以我们建立CP2类来记录点的信息。新建CP2类。如图8图8在CP2.h中添加以下代码:#includeRGB.hclass CP2 public:CP2();virtual CP2();CP2(double,double);CP2(double,double,CRGB);public:double x;double y;CRGB c;在CP2.cpp中添加以下代码:CP2:CP2()this-x=0.0;this-y=0.0;CP2:CP2()CP2:CP2(double x0,double y0)this-x=x0;this-y=y0;CP2:CP2(double x0,double y0,CRGB c0)this-x=x0;this-y=y0;this-c=c0;为记录点的颜色信息,我们建立CRGB类,用来实现点的颜色的实现。新建类型CRGB。如图9图9在RGB.h中添加以下代码:class CRGB public:CRGB();CRGB(double,double,double);friend CRGB operator +(CRGB&,CRGB &);friend CRGB operator *(double,CRGB &);virtual CRGB();public:double red;double green;double blue;在RGB.cpp中添加以下代码:CRGB:CRGB()this-red=0.0;this-green=0.0;this-blue=0.0;CRGB:CRGB(double r,double g,double b)this-red=r;this-green=g;this-blue=b;CRGB:CRGB()CRGB operator +(CRGB &c1,CRGB &c2)CRGB c;c.red=c1.red+c2.red;c.green=c1.green+c2.green;c.blue=c1.blue+c2.blue;return c;CRGB operator *(double k,CRGB &c1)CRGB c;c.red=k*c1.red;c.green=k*c1.green;c.blue=k*c1.blue;return c;为实现点、直线和矩阵的实现,我们添加CLine类。新建CLine。如图10如图10在Line.h中添加以下代码:#includeRGB.h#includeP2.hclass CLine public:CLine();virtual CLine();void MoveTo(CDC*,CP2);void MoveTo(CDC*,double,double,CRGB);void LineTo(CDC*,CP2);void LineTo(CDC*,double,double,CRGB);CRGB Interpolation(double,double,double,CRGB,CRGB);public:CP2 P0;CP2 P1;在Line.cpp中添加以下代码:void CLine:MoveTo(CDC*pDC,CP2 p0)P0=p0;void CLine:MoveTo(CDC*pDC,double x0,double y0,CRGB c0)P0.x=x0;P0.y=y0;P0.c=c0;void CLine:LineTo(CDC*pDC,CP2 p1)P1=p1;CP2 p,t;if(fabs(P0.x-P1.x)P1.y)t=P0;P0=P1;P1=t;for(p=P0;p.ySetPixel(ROUND(p.x),ROUND(p.y),RGB(p.c.red,p.c.green,p.c.blue);elsedouble k,d;k=(P1.y-P0.y)/(P1.x-P0.x);if(k1)if(P0.yP1.y)t=P0;P0=P1;P1=t;d=1-0.5*k;for(p=P0;p.ySetPixel(ROUND(p.x),ROUND(p.y),RGB(p.c.red,p.c.green,p.c.blue);if(d=0)p.x+;d+=1-k;else d+=1;if(0=k&kP1.x)t=P0;P0=P1;P1=t;d=0.5-k;for(p=P0;p.xSetPixel(ROUND(p.x),ROUND(p.y),RGB(p.c.red,p.c.green,p.c.blue);if(d=-1&kP1.x)t=P0;P0=P1;P1=t;d=-0.5-k;for(p=P0;p.xSetPixel(ROUND(p.x),ROUND(p.y),RGB(p.c.red,p.c.green,p.c.blue);if(d0)p.y-;d-=1+k;elsed-=k;if(k-1)if(P0.yP1.y;p.y-)p.c=Interpolation(p.y,P0.y,P1.y,P0.c,P1.c);pDC-SetPixel(ROUND(p.x),ROUND(p.y),RGB(p.c.red,p.c.green,p.c.blue);if(d0)p.x+;d-=1+k;elsed-=1;P0=p1;void CLine:LineTo(CDC*pDC,double x1,double y1,CRGB c1)LineTo(pDC,CP2(x1,y1,c1);CRGB CLine:Interpolation(double t,double t1,double t2,CRGB c1,CRGB c2)CRGB c;c=(t-t2)/(t1-t2)*c1+(t-t1)/(t2-t1)*c2;return c;绘制椭圆需要新建CCircle类来实现椭圆的绘制。新建CCircle类。如图11图11在Circle.h中添加以下代码:#includeRGB.h#includeP2.hclass CCircle public:CCircle();virtual CCircle();void Mbellipse(CDC*,CP2,CP2);void EllipsePoint(CDC*,double,double,CP2);在Circle.cpp中添加以下代码:void CCircle:Mbellipse(CDC*pDC,CP2 p1,CP2 p2)/椭圆的Bresenham算法double x,y,d1,d2;x=0;y=p1.y;d1=p1.y*p1.y+p1.x*p1.x*(-p1.y+0.25);EllipsePoint(pDC,x,y,p2);while(p1.y*p1.y*(x+1)p1.x*p1.x*(y-0.5)/椭圆AC弧段if (d10)if (d2SetPixel(ROUND(x+p2.x),ROUND(y+p2.y),rgb);pDC-SetPixel(ROUND(-x+p2.x),ROUND(y+p2.y),rgb);pDC-SetPixel(ROUND(x+p2.x),ROUND(-y+p2.y),rgb);pDC-SetPixel(ROUND(-x+p2.x),ROUND(-y+p2.y),rgb);到此准备工作完成,首先考虑为了区分各个程序的实现,在TextView.h中声明变量int m_DrawType;/绘图类型并且为了控制程序的状态声明两个BOLL累的变量m_isDraw与m_IsDrawIng。变量m_isDraw控制是否允许左键点下,而变量m_IsDrawIng控制程序的运行状态。点击查看中的建立类向导在CTextView中建立新建工具栏中所有图标的类向导.如图12图12在CTextView.cpp中添加以下代码:void CTextView:OnDrawline() / TODO: Add your command handler code herem_DrawType = 1;/1表示画笔m_isDraw = true;/初始状态为允许左键点下m_IsDrawIng=false;/初始状态为绘图状态void CTextView:OnDrawzhiline() / TODO: Add your command handler code herem_DrawType = 2;/2表示绘制直线段m_isDraw = true;/初始状态为允许左键点下m_IsDrawIng=false;/初始状态为绘图状态m_endpoint=m_OriginPoint;/初始化起始点与结束点void CTextView:OnDrawellipse() / TODO: Add your command handler code herem_DrawType = 3;/3表示椭圆m_isDraw=true;/初始状态为允许左键点下m_IsDrawIng=false;/初始状态为绘图状态void CTextView:OnDrawfang() / TODO: Add your command handler code herem_DrawType=4;/4表示矩形m_isDraw=true;/初始状态为允许左键点下m_IsDrawIng=false;/初始状态为绘图状态void CTextView:OnDrawellipseshi() / TODO: Add your command handler code herem_DrawType=7;/7表示椭圆区域m_isDraw=true;/当前处于绘图状态m_IsDrawIng=false;void CTextView:OnDrawfangshi() / TODO: Add your command handler code herem_DrawType=8;/8表示矩形区域m_isDraw=true;/当前处于绘图状态m_IsDrawIng=false;m_DrawType变量分别表示画笔,绘制直线段,椭圆,矩形,椭圆区域和矩形区域。同时需要在CTextView类的构造函数中添加如下代码:m_DrawType = 1;/默认初始绘图状态为绘制直线段m_isDraw = true;/当前处于绘图状态即应用程序的初始状态为绘制直线段。在TextView中声明变量CP2 m_OriginPoint、CP2 m_endpoint、CPoint m_StartPoint、CPoint m_EndPoint。建立类向导WM_LBUTTONDOWN,如图13。并且在OnLButtonDown中初始化所有变量。图13在OnLButtonDown中添加如下代码:if (m_isDraw)m_IsDrawIng=true;/将程序运行状态变为TUREm_OriginPoint.x=point.x;/初始化m_OriginPointm_OriginPoint.y=point.y;m_OriginPoint.c.red=rgbr;m_OriginPoint.c.blue=rgbb;m_OriginPoint.c.green=rgbg;m_StartPoint=point;/初始化m_StartPointm_EndPoint=point;/初始化m_EndPoint在TextView中声明函数void DrawMouseMove(UINT,CPoint)。建立类向导WM_MOSUEMOVE,如图14图14在OnMouseMove中添加以下代码:if (m_IsDrawIng&m_DrawType=1)/画笔DrawMouseMove(nFlags,point);if (m_IsDrawIng&m_DrawType=2)/直线段DrawMouseMove(nFlags,point);if (m_IsDrawIng&m_DrawType=7)/椭圆区域DrawMouseMove(nFlags,point);if (m_IsDrawIng&m_DrawType=8)/矩形区域DrawMouseMove(nFlags,point);在DrawMouseMove函数中添加如下代码:CClientDC dc(this);/构造设备环境对象if (m_IsDrawIng&m_DrawType=1)/判断鼠标移动的同时鼠标左键按下,并且要绘制的是画笔CP2 p;p.x=point.x;/初始化画笔信息p.y=point.y;p.c.red=rgbr;p.c.blue=rgbb;p.c.green=rgbg;if (m_IsDraw

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论