第十五课:文档系列化
一、在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();
评论