面向对象程序设计报告
——关于Drawcli的程序分析
一、 程序分析
1. 程序简介
Drawcli是一个微软MSDN中附带的一个示例程序,能够进行简单的绘图操作,主要包括16个.cpp文件,而每个.cpp文件都对应了一个.h文件。
2. 界面分析
在drawcli文件夹中有可执行程序,点击后进入主程序界面,它包含了一般Windows程序通有的一些结构。最上方是标题栏,再往下是菜单栏,翻译成中文,有文件、编辑、查看、绘画、对象、窗口、帮助七个下拉菜单,往下便是工具栏,包括新建、打开、保存、剪切、复制、粘贴、箭头、画图工具、打印、关于、帮助按钮,然后便是图形编辑界面,它是一个独立的窗口,已经给出了等间距的虚线,可以新建、打开、关闭等,以上就是打开程序后大概的界面。
3. 功能分析
该程序是一个简易的绘图程序,新建绘图页面后,可以在菜单栏中“Draw”的下拉菜单或者工具栏中的绘图工具按钮中选择需要的图形,分别有直线、矩形、圆角矩形、椭圆、点画多边形等画图模式,在编辑区通过鼠标的点击可以画出相应图形,并且可以实现拖动功能。在菜单栏中“Object”下拉菜单中选择对应功能,可以实现自定义线宽、填充颜、图层移动等功能。同时,在绘图的同时,也可以通过右键点击、工具栏按钮或者快捷键对图形进行复制、剪切、粘贴的操作。在绘图完成之后,用“Save”按钮或者“File”下拉菜单中的“Save”进行用户自定义路径的保存,保存默认格式为.drw。程序中的“About”和“Help”提供了程序的一些版本信息。
二、 源代码分析
1. 常量
在整个程序中,在很多地方定义了常量,例如形如const CRect & rect的常量引用的定义,形如void AssertValid() const的常量函数的定义,其中引用变量的使用,主要出现在函数自检传
值时,形参的定义,帮助实现了函数自检的地址传输,有利于数据在函数与函数之间的传递。程序中同样存在new运算符,即动态分配存储空间的使用,如CDrawObj* pClone = new CDrawObj(m_position)语句中即通过new申请了一块CDrawObj类大小的内存空间给与CDrawObj指针,与此相对的,运用了delete运算符将所申请的内存空间释放掉。对于作用域运算符::的使用,主要是在对类中已经申明的函数在类外进行定义时用到,如CDrawDoc类中声明的构造函数CDrawDoc()在另一个头文件中进行定义,其定义形式为CDrawDoc::CDrawDoc(),用以指明CDrawDoc()函数的存在区域。
2. 类
作为面向对象程序,其中含有大量的class类的定义,主要有四个绘图对象类,其中各类的主要说明如下:
2.1 class CDrawObj
其中CdrawObj是父类,不作为具体的绘图类对象存在。
class CDrawObj : public CObject { protected: DECLARE_SERIAL(CDrawObj); CDrawObj(); // Constructors public: CDrawObj(const CRect& position); // Attributes CRect m_position;//对象显示的位置 CDrawDoc* m_pDocument;//对象存储对应的文档对象指针enum函数 virtual int GetHandleCount();//获得对象特征点数量 virtual CPoint GetHandle(int nHandle);//获得对象特针点的位置 CRect GetHandleRect(int nHandleID, CDrawView* pView);//获得特征点的小矩形 virtual HCURSOR GetHandleCursor(int nHandle);//获得特征点的鼠标形状 virtual void SetLineColor(COLORREF color);//设置线条颜 virtual void SetFillColor(COLORREF color);//设置填充颜 // Operations virtual void Draw(CDC* pDC);//纯虚函数,由子对象自己实现 enum TrackerState { normal, selected, active };//对象的状态(一般、被选、活动) virtual void DrawTracker(CDC* pDC, TrackerState state);//绘出特征点 virtual void MoveTo(const CRect& positon, CDrawView* pView = NULL);//移动到一个新的位置,要求重绘 virtual int HitTest(CPoint point, CDrawView* pView, BOOL bSelected);//如果对象被选择,返回特征点;如果没有被选择,返回是否在对象内 virtual BOOL Intersects(const CRect& rect);//判断对象和矩形是否重叠 virtual void MoveHandleTo(int nHandle, CPoint point, CDrawView* pView = NULL);//通过特征点的移动来改变形状大小 virtual void OnOpen(CDrawView* pView);//调用OnEditProperties()来修改属性 virtual void OnEditProperties();//打开修改属性对话框,修改属性 virtual CDrawObj* Clone(CDrawDoc* pDoc = NULL);//创建一个新的CDrawObj对象,并加入到pDoc中 virtual void Remove();//delete自己 void Invalidate();//对应的m_pDocument对象更新所有视图 // Implementation public: virtual ~CDrawObj(); virtual void Serialize(CArchive& ar);//保存数据、读取数据 #ifdef _DEBUG void AssertValid(); #endif // implementation data protected: BOOL m_bPen;//是否使用笔 LOGPEN m_logpen;//笔的属性 BOOL m_bBrush;//是否使用刷子 LOGBRUSH m_logbrush;//刷子属性 }; |
2.2 CdrawRect
在CdrawObj中已经实现了许多功能,因此在CdrawRect中只是实现了需要修改和增加的函数。
class CDrawRect : public CDrawObj { protected: DECLARE_SERIAL(CDrawRect); CDrawRect(); public: CDrawRect(const CRect& position);//添加了对新数据成员的初始化 // Implementation public: virtual void Serialize(CArchive& ar);//添加了对新数据成员操作 virtual void Draw(CDC* pDC);//根据要求画出每个图形 virtual int GetHandleCount();//line和roundRectangle特殊处理 virtual CPoint GetHandle(int nHandle);//line和roundRectangle特殊处理 virtual HCURSOR GetHandleCursor(int nHandle);//line和roundRectangle特殊处理 virtual void MoveHandleTo(int nHandle, CPoint point, CDrawView* pView = NULL);//通过特征点来修改大小 virtual BOOL Intersects(const CRect& rect);//判断与图形是否存在相交 virtual CDrawObj* Clone(CDrawDoc* pDoc);//Clone一个新对象加入到pDoc中 protected: enum Shape { rectangle, roundRectangle, ellipse, line }; Shape m_nShape;//通过枚举变量来标示属于上述四种的哪一种形状 CPoint m_roundness; // for roundRect corners friend class CRectTool; }; |
2.2 CDrawPoly
class CDrawPoly; class CDrawPoly : public CDrawObj { protected: DECLARE_SERIAL(CDrawPoly); CDrawPoly(); public: CDrawPoly(const CRect& position); // Operations void AddPoint(const CPoint& point, CDrawView* pView = NULL);//增加新的点 BOOL RecalcBounds(CDrawView* pView = NULL);//计算这些点的外围大小 // Implementation public: virtual ~CDrawPoly(); virtual void Serialize(CArchive& ar); virtual void Draw(CDC* pDC); virtual void MoveTo(const CRect& position, CDrawView* pView = NULL); virtual int GetHandleCount(); virtual CPoint GetHandle(int nHandle); virtual HCURSOR GetHandleCursor(int nHandle); virtual void MoveHandleTo(int nHandle, CPoint point, CDrawView* pView = NULL); virtual BOOL Intersects(const CRect& rect); virtual CDrawObj* Clone(CDrawDoc* pDoc); protected: int m_nPoints; int m_nAllocPoints; CPoint* m_points; CDrawPoly* m_pDrawObj; friend class CPolyTool; }; |
2.3 CDrawOleObj
class CDrawOleObj : public CDrawObj { protected: DECLARE_SERIAL(CDrawOleObj); CDrawOleObj(); public: CDrawOleObj(const CRect& position); // Implementation public: virtual void Serialize(CArchive& ar); virtual void Draw(CDC* pDC); virtual CDrawObj* Clone(CDrawDoc* pDoc); virtual void OnOpen(CDrawView* pView); virtual void MoveTo(const CRect& positon, CDrawView* pView = NULL); virtual void OnEditProperties(); virtual void Remove(); virtual ~CDrawOleObj(); static BOOL c_bShowItems; CDrawItem* m_pClientItem; CSize m_extent; // current extent is tracked separate from scaled position }; |
另外存在29处自定义的新类,并且所有的类的定义均在头文件中完成。大部分的类的定义中都用到了两种或以上的访问限制符,如CDrawDoc类中用到了public和protect两种访问限制符。每个类中大都定义了一定数量的构造函数,包含各种类型的构造函数。如类CProperty中含有CProperty( void )函数和CProperty( DWORD dwID, const LPVOID pValue, DWORD dwType )函数,类CRectDlg中含有的构造函数CRectDlg(CWnd* pParent = NULL),其中前者是无参构造函数,后者则为一般构造函数,第三个构造函数则为复制构造函数。与构造函数相对的,类中必然定义了与此对应的析构函数,用于撤销该类,如class CDrawView中的函数virtual ~CDrawView()则为其对应的析构函数。类中还含有大量的一般成员函数,主要执行访问本类数据成员以及完成本类主要功能的任务。如CDrawView类中的void Select(CDrawObj* pObj, BOOL bAdd = FALSE),CDrawDoc类中的CDrawObjList* GetObjects()等函数即是一般成员函数。其中CDrawObjList* GetObjects()函数的主要功能为返回一个地址值。关于this指针的运用,程序中主要将其进行隐式调用,一般在运算符重载,调用成员函数时用到。C++中的静态成员在此程序中亦有用到,如类CDrawOleObj中的static BOOL c_bShowItems;即为静态数据成员。为了在程序中建立类与类之间联系,提高程序执行效率,降低程序中消息在类与类之间传递而带来的开销,各个代码中也包括友元函数和友元类,如类COleDataSource中的friend class COleServerItem,即为友元类。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论