yle (width)
public:
CTypedPtrList m_strokeList;
//获取当前使用的画笔,为视图所使用
CPen* GetCurrentPen() { return &m_penCur; }
protected:
CSize m_sizeDoc;
public:
CSize GetDocSize() { return m_sizeDoc; }
// Operations
public:
//往链表里增加一个笔划
CStroke* NewStroke();
// Operations
//用于初始化文档
protected:
void InitDocument();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDrawDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CDrawDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CDrawDoc)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
这里我们使用 指针链表模板来保存指向每个笔划的指针:
CTypedPtrList m_strokeList;
其中“<>”第一个参数表示链表基本类型,第二个参数代表链表中所存放的元素的类型。
为了使用模板,还要修改stdafx.h,在其中加入afxtempl..h头文件,它包含了使用模板时所需的类型定义和宏:
//.........
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include // MFC core and standard components
#include // MFC extensions
#include // MFC templates
#include // MFC OLE automation classes
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
//......
由于绘图程序需要卷滚文档,因此象前面的编辑那样,增加一个m_sizeDoc数据成员存放文档的大小。另外,还需要提供一个GetDocSize()来访问它。NewStroke()用于往链表里增加一个笔划。
现在,开始设计CStroke类。笔划可以看作由一系列点组成,这样CStroke可以用一个点的数组来表示。另外,还需要一些成员函数来访问这个数组。我们还希望笔划能够自己绘制自己,并用串行化机制保存自己的数据。
CStroke类定义清单如8.4,我们把它在CDrawDoc类定义之前。
清单8.4 CStroke类定义
class CStroke : public CObject
{
public:
CStroke(UINT nPenWidth);//用笔的宽度构造一个画笔
//用于串行化笔划对象
protected:
CStroke(); //串行化对象所需的不带参数的构造函数
DECLARE_SERIAL(CStroke)
// Attributes
protected:
UINT m_nPenWidth; // one pen width applies to entire stroke
public:
//用数组模板类保存笔划的所有点
CArray m_pointArray; // series of connected points
//包围笔划所有的点的一个最小矩形,关于它的作用以后会提到
CRect m_rectBounding; // smallest rect that surrounds all
// of the points in the stroke
// measured in MM_LOENGLISH units
// (0.01 inches, with Y-axis inverted)
public:
CRect& GetBoundingRect() { return m_rectBounding; }
//结束笔划,计算最小矩形
void FinishStroke();
// Operations
public:
//绘制笔划
BOOL DrawStroke(CDC* pDC);
public:
virtual void Serialize(CArchive& ar);
};
文档的初始化
文档的初始化在OnNewDocument()和OnOpenDocument()中完成。对于Draw程序来说,两者的初始化相同,因此设计一个InitDocument()函数用于文档初始化:
void CDrawDoc::InitDocument()
{
m_nPenWidth=2;
m_nPenCur.CreatePen(PS_SOLID,m_nPenWidth,RGB(0,0,0));
//缺省文档大小设置为800X900个逻辑单位
m_sizeDoc = CSize(800,900);
}
InitDocument()函数将笔的宽度初值设为2,然后创建一个画笔对象。该对象在以后绘图是要用到。最后将文档尺寸大小设置为800X900个逻辑单位。
然后在OnNewDocument()和OnOpenDocument()中调用它:
void CDrawDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
InitDocument();
return TRUE;
}
AppWizard并没有生成OnOpenDocument()的代码,因此要用ClassWizard来生成OnOpenDocument()的框架。生成框架后,在其中加入代码:
BOOL CDrawDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
// TODO: Add your specialized creation code here
InitDocument();
ret