孙鑫13课文档与串行化.docx
- 文档编号:28282743
- 上传时间:2023-07-10
- 格式:DOCX
- 页数:16
- 大小:19.41KB
孙鑫13课文档与串行化.docx
《孙鑫13课文档与串行化.docx》由会员分享,可在线阅读,更多相关《孙鑫13课文档与串行化.docx(16页珍藏版)》请在冰豆网上搜索。
孙鑫13课文档与串行化
先建立一个MFC的单文档程序。
在框架上增加两个按钮,文件操作下面的读取文件和写入文件。
并且在视类中增加消息响应函数。
下面用CArchive类对文件进行操作。
使对象持久性。
将CArchive类保存在持久的对象上,比如磁盘等。
下次去打开程序时,从磁盘读取,在内存中重现。
voidCGraphicView:
:
OnFileWrite()
{
//TODO:
Addyourcommandhandlercodehere
CFileFile("1.txt",CFile:
:
modeCreate|CFile:
:
modeWrite);
CArchivear(&File,CArchive:
:
store);
inti=4;
charc='a';
floatf=1.3f;
CStringstr="http:
//sunxin.org";
ar<
}
则在"1.txt"中会有写入的数据;
voidCGraphicView:
:
OnFileRead()
{
//TODO:
Addyourcommandhandlercodehere
//CFileFile=CFile("1.txt",CFile:
:
modeCreate|CFile:
:
modeWrite);
//CArchive(&File,UINTnMode,intnBufSize=4096,void*lpBuf=NULL);
CFileFile("1.txt",CFile:
:
modeRead);
CArchivear(&File,CArchive:
:
load);
inti/*=4*/;
charc/*='a'*/;
floatf/*=1.3f*/;
CStringstr/*="http:
//sunxin.org"*/;
ar>>i>>c>>f>>str;
CStringstrtemp;
strtemp.Format("%i-%c-%f-%s",i,c,f,str);
MessageBox(strtemp);
}
OnNewDocument();CalledbytheframeworkaspartoftheFileNewcommand.在程序启动的时候被调用。
文件新建时会调用这个函数,因此可以在这个函数中修改文档的标题。
代码如下:
在BOOLCGraphicDoc:
:
OnNewDocument()中加入
SetTitle("sunxin");
或者在IDR_MAINFRAME字符串中修改:
Graphic\n\nGraphi\n\n\nGraphic.Document\nGraphiDocument
CDocTemplate:
:
GetDocString()函数中有对这七个字符串的具体的说明。
若要程序支持另外一种类型的文档,需在BOOLCGraphicApp:
:
InitInstance()再次构造一个文档模板,并将它加入进去。
这样IDR_MAINFRAME第三个字符串的内容会出现在文件/新建对话框中。
下面增加了第4、5项
windowTitle\ndocName\nGraphi\nWorksheets(*.xls)\n.xls\nGraphic.Document\nGraphiDocument
下面是IDR_MAINFRAME的7个说明:
⏹
(1)CDocTemplate:
:
windowTitle,主窗口标题栏上的字符串,MDI程序不需要指定,将以IDR_MAINFRAME字符串为默认值。
⏹
(2)CDocTemplate:
:
docName,缺省文档的名称。
如果没有指定,缺省文档的名称是无标题。
⏹(3)CDocTemplate:
:
fileNewName,文档类型的名称。
如果应用程序支持多种类型的文档,此字符串将显示在"File/New"对话框中。
如果没有指定,就不能够在"File/New"对话框处理这种文件。
⏹(4)CDocTemplate:
:
filterName,文档类型的描述和一个适用于此类型的通配符过滤器。
这个字符串将出现在“File/Open”对话框中的文件类型列表框中。
要和CDocTemplate:
:
filterExt一起使用。
⏹(5)CDocTemplate:
:
filterExt,文档的扩展名。
如果没有指定,就不能够在“File/Open”对话框中处理这种文档。
要和CDocTemplate:
:
filterName一起使用。
⏹(6)CDocTemplate:
:
regFileTypeId,如果你以:
:
RegisterShellFileTypes向系统的注册表注册文件类型,此值会出现在HEY_CLASSES_ROOT之下成为其子项,并仅供Windows内部使用。
如果没有指定,这种文件类型就无法注册。
⏹(7)CDocTemplate:
:
regFileTypeName,这也是存储在注册表中的文件类型名称。
它会显示于程序中用以访问注册表的对话框内。
Document/View结构
⏹在MFC中,文档类负责管理数据,提供保存和加载数据的功能。
视类负责数据的显示,以及给用户提供对数据的编辑和修改功能。
⏹MFC给我们提供Document/View结构,将一个应用程序所需要的“数据处理与显示”的函数空壳都设计好了,这些函数都是虚函数,我们可以在派生类中重写这些函数。
有关文件读写的操作在CDocument的Serialize函数中进行,有关数据和图形显示的操作在CView的OnDraw函数中进行。
我们在其派生类中,只需要去关注Serialize和OnDraw函数就可以了,其它的细节我们不需要去理会,程序就可以良好地运行。
⏹当我们按下“File/Open”,ApplicationFramework会激活文件打开对话框,让你指定文件名,然后自动调用CGraphicDoc:
:
Serialize读取文件。
ApplicationFramework还会调用CGraphicView:
:
OnDraw,传递一个显示DC,让你重新绘制窗口内容。
⏹MFC给我们提供Document/View结构,是希望我们将精力放在数据结构的设计和数据显示的操作上,而不要把时间和精力花费在对象与对象之间、模块与模块之间的通信上。
⏹一个文档对象可以和多个视类对象相关联,而一个视类对象只能和一个文档对象相关联。
在voidCGraphicDoc:
:
Serialize(CArchive&ar)//保存数据和加载数据
{
if(ar.IsStoring())
{
//TODO:
addstoringcodehere
inti=4;
charc='a';
floatf=1.3f;
CStringstr="http:
//sunxin.org";
ar<
}
else
{
//TODO:
addloadingcodehere
inti;
charc;
floatf;
CStringstr;
ar>>i>>c>>f>>str;
CStringstrtemp;
strtemp.Format("%i-%c-%f-%s",i,c,f,str);
AfxMessageBox(strtemp);
}
}
//CArchive&ar只能一次关联一个文档对象,比如先保存,保存可以成功,但是要再次打开,就成功不了了,除非换一个文档对象。
文件新建和文件打开都是在CGraphicApp当中,它负责管理文档管理器。
文档管理器有一个指针链表,管理文档模板。
文档模板管理框架类,视类,文档类,三位一体来为一个文档服务。
用CArchive类保存一个对象,则这个类必须支持串行化。
将11课的Graph.cpp和Graph.h拷贝到本课工程目录下,加入到工程下。
将//#include"Graphic.h"注释起来。
下面是一个类支持串行化的5个操作步骤:
(直接写修改后的代码,红色表示改变)
classCGraph:
publicCObject
{
public:
DECLARE_SERIAL(CGraph)
voidSerialize(CArchive&archive);
CPointm_ptOrigin;
CPointm_ptEnd;
UINTm_nDrawType;
CGraph();
CGraph(UINTm_nDrawType,CPointm_ptOrigin,CPointm_ptEnd);
virtual~CGraph();
};
voidCGraph:
:
Serialize(CArchive&archive)
{
//callbaseclassfunctionfirst
//baseclassisCObjectinthiscase
CObject:
:
Serialize(archive);
//nowdothestuffforourspecificclass
if(archive.IsStoring())
archive< else archive>>m_nDrawType>>m_ptOrigin>>m_ptEnd; } 第三步的DefiningaConstructorwithNoArguments,CGraph类中已有,此步不用。 在Graph.cpp中加入IMPLEMENT_SERIAL(CPerson,CObject,1)。 至此,CGraph类支持串行化。 给CGraph类增加一个图形绘制的函数,将图形绘制和数据封装到一个类中,符合面向对象程序设计风格。 增加的函数为voidOnDraw(CDC*pDC); voidCGraph: : OnDraw(CDC*pDC) { CBrush*pbrush=(CBrush*)pDC->SelectStockObject(NULL_BRUSH); switch(m_nDrawType) { case1: pDC->SetPixel(m_ptEnd,RGB(255,0,0)); break; case2: pDC->MoveTo(m_ptOrigin); pDC->LineTo(m_ptEnd); break; case3: pDC->Rectangle(CRect(m_ptOrigin,m_ptEnd)); break; case4: pDC->Ellipse(CRect(m_ptOrigin,m_ptEnd)); break; default: break; } pDC->SelectObject(pbrush); } 增加四个菜单项: 点,直线,矩形,椭圆;并且增加命令响应。 (视类中) 为视类增加: private: UINTm_dwstyle; CPointm_dnpt; 在视类构造函数中给这两个赋值。 voidCGraphicView: : OnDot() { //TODO: Addyourcommandhandlercodehere m_dwstyle=1; } voidCGraphicView: : OnLine() { //TODO: Addyourcommandhandlercodehere m_dwstyle=2; } voidCGraphicView: : OnRectangle() { //TODO: Addyourcommandhandlercodehere m_dwstyle=3; } voidCGraphicView: : OnEllipse() { //TODO: Addyourcommandhandlercodehere m_dwstyle=4; } voidCGraphicView: : OnLButtonDown(UINTnFlags,CPointpoint) { //TODO: Addyourmessagehandlercodehereand/orcalldefault m_dnpt=point; CView: : OnLButtonDown(nFlags,point); } 为视类增加: public: CObArraym_obarray; 和#include"Graph.h"和#include"Graph.h" voidCGraphicView: : OnLButtonUp(UINTnFlags,CPointpoint) { //TODO: Addyourmessagehandlercodehereand/orcalldefault CClientDCdc(this); CDC*pDC=&dc; CBrush*pbrush=(CBrush*)pDC->SelectStockObject(NULL_BRUSH); switch(m_dwstyle) { case1: pDC->SetPixel(m_dnpt,RGB(255,0,0)); break; case2: pDC->MoveTo(m_dnpt); pDC->LineTo(point); break; case3: pDC->Rectangle(CRect(m_dnpt,point)); break; case4: pDC->Ellipse(CRect(m_dnpt,point)); break; default: break; } pDC->SelectObject(pbrush); CGraph*pgraph=newCGraph(m_dwstyle,m_dnpt,point); m_obarray.Add(pgraph); CView: : OnLButtonUp(nFlags,point); } 接下来在voidCGraphicDoc: : Serialize(CArchive&ar)将在集合类中保存的数据写入到文件中。 在GraphicDoc.cpp中加入#include"GraphicView.h" voidCGraphicDoc: : Serialize(CArchive&ar)//保存数据和加载数据 { POSITIONpos=GetFirstViewPosition(); CGraphicView*pView=(CGraphicView*)GetNextView(pos); if(ar.IsStoring()) { //TODO: addstoringcodehere intcount=pView->m_obarray.GetSize(); ar< for(inti=0;i { ar< } } else { intncount; ar>>ncount; CGraph*pgraph;//自动调用不带参数的构造函数来构造这个对象,因此不需要给它分配内存空间。 for(inti=0;i { ar>>pgraph; pView->m_obarray.Add(pgraph); } } } voidCGraphicView: : OnDraw(CDC*pDC) { CGraphicDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); intcount; count=m_obarray.GetSize(); for(inti=0;i { ((CGraph*)m_obarray.GetAt(i))->OnDraw(pDC); } //TODO: adddrawcodefornativedatahere } CGraphicDoc: : Serialize(CArchive&ar)实际上调用CGraph: : Serialize(CArchive&archive)来完成的。 由框架自动完成。 CObArrayincorporatestheIMPLEMENT_SERIALmacrotosupportserializationanddumpingofitselements.意思是CObArray本身也支持串行化。 下面来利用CObArray本身的串行化保存数据。 voidCGraphicDoc: : Serialize(CArchive&ar)//保存数据和加载数据 { POSITIONpos=GetFirstViewPosition(); CGraphicView*pView=(CGraphicView*)GetNextView(pos); if(ar.IsStoring()) { //TODO: addstoringcodehere //intcount=pView->m_obarray.GetSize(); //ar< //for(inti=0;i //{ //ar< //} } else { //intncount; //ar>>ncount; //CGraph*pgraph;//自动调用不带参数的构造函数来构造这个对象,因此不需要给它分配内存空间。 //for(inti=0;i //{ //ar>>pgraph; //pView->m_obarray.Add(pgraph); //} } pView->m_obarray.Serialize(ar); 既然文档类是存储数据的,则将CObArraym_obarray;的定义放到DOC类当中。 (删除视类的) voidCGraphicView: : OnLButtonUp(UINTnFlags,CPointpoint)中的代码修改如下: GetDocument()->m_obarray.Add(pgraph); 在voidCGraphicView: : OnDraw(CDC*pDC)中修改如下: voidCGraphicView: : OnDraw(CDC*pDC) { CGraphicDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); intcount; count=pDoc->m_obarray.GetSize(); for(inti=0;i { ((CGraph*)pDoc->m_obarray.GetAt(i))->OnDraw(pDC); } //TODO: adddrawcodefornativedatahere } 在voidCGraphicDoc: : Serialize(CArchive&ar)中修改如下: m_obarray.Serialize(ar); 不管是新建一个文档(OnNewDocument)还是打开一个文档(OnOpenDocument),都会调用DeleteContents来ensurethatthedocumentisemptyandthenmarksthenewdocumentasclean.此工程是单文档,只有一个文档对象,它要被反复的调用,应该在此文档对象被再次使用前,删除其数据。 virtualvoidDeleteContents(); voidCGraphicDoc: : DeleteContents() { //TODO: Addyourspecializedcodehereand/orcallthebaseclass intcount; count=m_obarray.GetSize(); for(inti=0;i { deletem_obarray.GetAt(i);//删除指针的堆内存,删除指针值 m_obarray.RemoveAt(i,1); } CDocument: : DeleteContents(); } 这段代码有问题,因为RemoveAt: Removesoneormoreelementsstartingataspecifiedindexinanarray.Intheprocess,itshiftsdownalltheelementsabovetheremovedelement(s).Itdecrementstheupperboundofthearraybutdoesnotfreememory. 正确的代码: voidCGraphicDoc: : DeleteContents() { //TODO: Addyourspecializedcodehereand/orcallthebaseclass //intcount; //count=m_obarray.GetSize(); for(inti=0;i { deletem_obarray.GetAt(i);//删除指针的堆内存,删除指针值 m_obarray.RemoveAt(i,1); } CDocument: : DeleteContents(); } 或者: voidCGraphicDoc: : DeleteContents() { //TODO: Addyourspecializedcodehereand/orcallthebaseclass intcount; count=m_obarray.GetSize(); for(inti=0;i { deletem_obarray.GetAt(i);//删除指针的堆内存,删除指针值 //m_obarray.RemoveAt(i,1); } m_obarray.RemoveAll();//移除所有元素 CDocument: : DeleteContents(); } 或者: voidCGr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 孙鑫 13 课文 串行