第十五课:文档系列化 一、在View中存取文件: 1. 用Carchive写文件: CFileDialog dlg(false); if (IDOK==dlg.DoModal()) { CFile f(dlg.GetPathName(),CFile::modeCreate|CFile::modeWrite ); CArchive ar(&f,CArchive::store); CString str("abc"); ar<<3<<'c'<<6.6f<<str; } 2. 用Carchive读文件: CFileDialog dlg(true); if (IDOK==dlg.DoModal()) { CFile f(dlg.GetPathName(),CFile::modeRead); CArchive ar(&f,CArchive::load); int x; char c; float d; CString st; ar>>x>>c>>d>>st; CString str; str.Format("%d,%c,%f,%s",x,c,d,st); MessageBox(str); } 说明: a. 在代码中一个小数被默认为double类型; b. Carchive 是Cfile的包装类,简化了存取文件的操作,但它只能存取有限种数据类型。 二、在Docment类中存取文件: 在Docment类的Serialize函数中加入: if (ar.IsStoring()) { CString str("abc"); ar<<3<<'c'<<6.6f<<str; } else { int x; char c; float d; CString st; ar>>x>>c>>d>>st; CString str; str.Format("%d,%c,%f,%s",x,c,d,st); MessageBox(NULL,str,0,0); } 说明: 1. 这段代码等效于“一”中的存取文件的代码。 2. Serialize函数会在用户点击MFC提供的有关文件的菜单时自动被调用,在调用之前,MFC会首先生成一个标准文件对话框,再根据用户的选择生成一个Cfile,再生成一个Carchive,把它传入Serialize。这大大简化了程序员的工作。 三、画线并将数据保存成文件: 1、 定义一个可序列化的类Cline: a. 新建一个类,从Cobject派生,(在Class type中要选Generic Class,否则基类选不了Cobject。在类名中输入Cline; b. 在Cline中覆盖Serialize成员函数。 c. 在类的声明中使用DECLARE_SERIAL宏: DECLARE_SERIAL( Cline) d. 定义一个一不带参数的构造函函数。 e. 在类的实现文件中使用IMPLEMENT_SERIAL宏: IMPLEMENT_SERIAL( CMygraph, CObject, 1 ) f.加入两个成员变量,记录一条线的起点和终点: CPoint m_ptOrigin; CPoint m_ptEnd; 2、 在Document类中定义一个成员变量,用于保存每一根线的数据: CObArray m_lnArray; 3、 在View类中加入WM_LBUTTONDOWN,WM_LBUTTONUP的响应函数,并加入一个成员变量,用于记录一条线的起点: CPoint m_ptOrigin; 4、 在OnLButtonDown中: m_ptOrigin=point; 5、 在OnLButtonUp中: Cline *pLine=new Cline(); pline->m_ptOrigin=m_ptOrigin; pline->m_ptEnd=point; GetDocument()->m_lnArray.Add(pLine); Invalidate(); 6、 在View类的OnDraw函数中加入: int x=pDoc->m_graphArray.GetSize(); for (int i=0;i<x;i++) { pDC->MoveTo(((Cline*)pDoc->m_lnArray.GetAt(i))->m_ptOrigin); pDC->LineTo(((CLine*)pDoc->m_lnArray.GetAt(i))->m_ptEnd); } 7、 在Document类中的Serialize函数中: m_lnArray.Serialize(ar); 四、DeleteContent: 在document类中加入DeleteContent虚函数,它会在用户点击“打开”和“新建”菜单时自动调用,这是删除文档数据的最好时机。删除时有两种常见的错误: 1.错误方法一: for (int i=0;i<m_lnArray.GetSize();i++) delete (Cline*)m_lnArray.GetAt(i); m_lnArray.RemoveAll(); 原因:每循环一次,m_lnArray.GetSize()返回的值都会减小,造成数据的漏删。 2.错误方法二: int index=lnArray.GetSize(); for (int i=0;i<index;i++) { delete (Cline*)m_graphArray.GetAt(i); m_lnArray.RemoveAt(i); } 原因:每删除一个数组元素,数组都会重新排序,它的下标会变。 3.正确方法: int index=m_lnArray.GetSize(); while(index--) delete (Cline*)m_lnArray.GetAt(index); m_lnArray.RemoveAll();

评论