孙鑫VC++视频教程笔记(13)文档与串行化_double强制转换成float-程序员宅基地

技术标签: 文档  VC++深入讲解(孙鑫)  file  function  vc++  mfc  microsoft  

把文件在磁盘上保存下来 叫做串行化
可以使用CArchive:
写入:
 CFile file("1.txt",CFile::modeCreate | CFile::modeWrite);
 CArchive ar(&file,CArchive::store);
 int i=4;
 float b=1.3f;   //C默认用float定义而不加f的为double型
 CString str="SongPeng";
 ar<<i<<b<<str;
读取:
 CFile file("1.txt",CFile::modeRead);
 CArchive ar(&file,CArchive::load);
 int i;
 float b;
 CString str;
 CString strRestult;
 ar>>i>>b>>str;
 strRestult.Format("%d %f %s",i,b,str);
 MessageBox(strRestult);
在BOOL CGraphicDoc::OnNewDocument()中,我们可以设置文档,例如:
 SetTitle("SongPeng")
 
OnNewDocument()用来在程序运行之初构造文档,或是新建文档:
Called by the framework as part of the File New command. The default implementation of this function calls the DeleteContents member function to ensure that the document is empty and then marks the new document as clean. Override this function to initialize the data structure for a new document. You should call the base class version of this function from your override.

我们已可以在String Table中修改标题,其中的IDR_MAINFRAME中的字串原为:
Graphic/n/nGraphi/n/n/nGraphic.Document/nGraphi Document
各子串之间用/n分割,可以有空子串。
各子串定义如下:
CDocTemplate::windowTitle   Name that appears in the application window’s title bar (for example, “Microsoft Excel”). Present only in the document template for SDI applications.


CDocTemplate::docName   Root for the default document name (for example, “Sheet”). This root, plus a number, is used for the default name of a new document of this type whenever the user chooses the New command from the File menu (for example, “Sheet1” or “Sheet2”). If not specified, “Untitled” is used as the default.


CDocTemplate::fileNewName   Name of this document type. If the application supports more than one type of document, this string is displayed in the File New dialog box (for example, “Worksheet”). If not specified, the document type is inaccessible using the File New command.


CDocTemplate::filterName   Description of the document type and a wildcard filter matching documents of this type. This string is displayed in the List Files Of Type drop-down list in the File Open dialog box (for example, “Worksheets (*.xls)”). If not specified, the document type is inaccessible using the File Open command.


CDocTemplate::filterExt   Extension for documents of this type (for example, “.xls”). If not specified, the document type is inaccessible using the File Open command.


CDocTemplate::regFileTypeId   Identifier for the document type to be stored in the registration database maintained by Windows. This string is for internal use only (for example, “ExcelWorksheet”). If not specified, the document type cannot be registered with the Windows File Manager.


CDocTemplate::regFileTypeName   Name of the document type to be stored in the registration database. This string may be displayed in dialog boxes of applications that access the registration database (for example, “Microsoft Excel Worksheet”).

在前两个/n之间加入字符串,就达到修改标题的效果。

在新建工程的第四部advance选项中也能进行修改

凡是从CCmdTarget派生出的类,都可以间接接受命令消息

新建文档运行路径:
void CWinApp::OnFileNew()--->void CDocManager::OnFileNew()---> 
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();--->
pTemplate->OpenDocumentFile(NULL);--->CDocument*
CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
 BOOL bMakeVisible)--->pDocument = CreateNewDocument();
--->pFrame = CreateNewFrame(pDocument, NULL);--->
if (!pDocument->OnNewDocument())--->BOOL CGraphicDoc::OnNewDocument()

CWinApp负责管理文档管理器

打开文档运行路径
void CWinApp::OnFileOpen()--->void CDocManager::OnFileOpen()--->
DoPromptFileName--->BOOL CDocManager::DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)--->打开一个文件--->AfxGetApp()->OpenDocumentFile(newName);--->
CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)--->
CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)--->
match = pTemplate->MatchDocType(szPath, pOpenDocument);--->
判断pOpenDocument是否为空,pOpenDocument用来指定是否与先前的文档关联,即获取先前相同文档的指针,如果是,不再对文档进行操作---->
CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
 BOOL bMakeVisible)--->if (pDocument == NULL)--->if (pFrame == NULL)--->
if (lpszPathName == NULL)--->if (!pDocument->OnOpenDocument(lpszPathName))--->
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)---->
Serialize(loadArchive);---->void CGraphicDoc::Serialize(CArchive& ar)

生成可串行化的类:
 A serializable class usually has a Serialize member function, and it usually uses the DECLARE_SERIAL and IMPLEMENT_SERIAL macros, as described under class CObject.
分为五步:
1 . Deriving your class from CObject (or from some class derived from CObject).
2 . Overriding the Serialize member function.
3 . Using the DECLARE_SERIAL macro in the class declaration. 
4 . Defining a constructor that takes no arguments.
5 . Using the IMPLEMENT_SERIAL macro in the implementation file for your class.
IMPLEMENT_SERIAL(CGraph,CObject,1),1为版本号,保存和读取时版本号必须相同
一个文档类对象能和多个视类对象相关,一个视类对象只和一个文档类对象相关.

单文档类只有一个视类对象,要获取视类对象的指针
要在文档类中访问定义在视类中的对象,首先要获得视类的指针.需要用到函数
CDocument::GetFirstViewPosition 得到视类对象的位置
virtual POSITION GetFirstViewPosition( ) const;
A POSITION value that can be used for iteration with the GetNextView member function.
Call this function to get the position of the first view in the list of views associated with the document.
然后再调用GetNextView得到视类对象的指针
 POSITION pos=GetFirstViewPosition();
 CGraphicView *pView=(CGraphicView *)GetNextView(pos);

POSITION   A value used to denote the position of an element in a collection; used by MFC collection classes.

我们文档类中调用Serialize保存一个可串行化的类的数据时实际上是利用了这个对象本身的Serialize函数,这个对象需要什么对象,都需要在你编写可串行化的类时去确定

void CGraph::Serialize(CArchive &ar)
{
 if(ar.IsStoring())
 {
  ar<<m_nDrawType<<m_pOrigin<<m_pEnd;
 }
 else
 {
  ar>>m_nDrawType>>m_pOrigin>>m_pEnd;
 }
}

void CGraphicDoc::Serialize(CArchive& ar)
{
 POSITION pos=GetFirstViewPosition();
 CGraphicView *pView=(CGraphicView *)GetNextView(pos);
 if (ar.IsStoring())
{
  int nCount=pView->m_obArray.GetSize();
  ar<<nCount;
  for(int i=0;i<nCount;i++)
  {
   ar<<pView->m_obArray.GetAt(i);
  }
 }
 else
 {
  int nCount;
  ar>>nCount;
  CGraph *pGraph;
  for(int i=0;i<nCount;i++)
  {
   ar>>pGraph;
   pView->m_obArray.Add(pGraph);
  }
 }
}

数组的保存:
 CGraph *pGraph=new CGraph(m_nDrawType,m_pOrigin,point);
 m_obArray.Add(pGraph);

CObArray incorporates the IMPLEMENT_SERIAL macro to support serialization and dumping of its elements. If an array of CObject pointers is stored to an archive, either with the overloaded insertion operator or with the Serialize member function, each CObject element is, in turn, serialized along with its array index
void CGraphicDoc::Serialize(CArchive& ar)可被修改为:
void CGraphicDoc::Serialize(CArchive& ar)
{
 POSITION pos=GetFirstViewPosition();
 CGraphicView *pView=(CGraphicView *)GetNextView(pos);
 if (ar.IsStoring())
{
}
else
{
}
pView->m_obArrary.Serialize(ar);
}

以下是CObArray在MFC中的源代码:
void CObArray::Serialize(CArchive& ar)
{
 ASSERT_VALID(this);

 CObject::Serialize(ar);

 if (ar.IsStoring())
 {
  ar.WriteCount(m_nSize);
  for (int i = 0; i < m_nSize; i++)
   ar << m_pData[i];
 }
 else
 {
  DWORD nOldSize = ar.ReadCount();
  SetSize(nOldSize);
  for (int i = 0; i < m_nSize; i++)
   ar >> m_pData[i];
 }
}

文档类时用来管理数据的我们把CObArray m_obArray放入文档类中
以下为自动生成类,这是在View类中准备好的可以获得文档来指针的函数:
CGraphicDoc* CGraphicView::GetDocument() // non-debug version is inline
{
 ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraphicDoc)));
 return (CGraphicDoc*)m_pDocument;
}

 在View中可以这样调用m_obArray
CGraphicDoc *pDoc=GetDocument();
 pDoc->m_obArray.Add(pGraph);

Document/View结构
在MFC中,文档类负责管理数据,提供保存和数据加载的功能。视类负责数据的显示,以及给用户提供对数据的编辑和修改功能。
MFC给我们提供Document/View结构,将一个应用程序所需要的数据处理与显示的函数的空壳都设计好了,这些函数都是需函数,我们可以在派生类中重写这些函数。有关文件读写的操作在CDocument的Serialize函数中进行,有关数据和图形显示的操作在CView的OnDraw函数中进行。我们在其派生类中,只需要去关注serialize和OnDraw函数就可以了,其他的细节我们不需要去理会,程序就可以良好的运行。
当我么按下"File/Open",Application Framework会激活文件打开对话框,让你指定文件名,然后自动调用CGraphicView::OnDraw,传递一个显示DC,让你重新绘制窗口内容。
MFC给我们提供Document/View结构,是希望我们将精力放在数据结构的设计和数据显示的操作上,而不是把时间和精力花费在对象与对象之间,模块与模块之间的通信上。
一个文档对象可以和多个视类对象相关联,而一个视类对象只能和一个文档类对象相关联

不管是新建文档还是打开另外一份文档,都会调用DeletContents,以保证新建文档时空的

释放对内存
void CGraphicDoc::DeleteContents()
{
 // TODO: Add your specialized code here and/or call the base class
 int nCount;
 nCount=m_obArray.GetSize();
 for(int i=0;i<nCount;i++)
 {
  delete m_obArray.GetAt(i);  //解除指针与值之间的联系,但没有清除堆内存
  m_obArray.RemoveAt(i);  //清除堆内存
 }
 CDocument::DeleteContents();
}
CDocument::DeleteContents()会在打开,新建,关闭文档时被调用

CObArray::RemoveAt
Removes one or more elements starting at a specified index in an array. In the process, it shifts down all the elements above the removed element(s). It decrements the upper bound of the array but does not free memory.RemoveAt会导致数组中数据的重排
因此,需要把以上代码修改为
void CGraphicDoc::DeleteContents()
{
 // TODO: Add your specialized code here and/or call the base class
 int nCount;
 nCount=m_obArray.GetSize();
 for(int i=0;i<nCount;i++)
 {
  delete m_obArray.GetAt(i);
 }
 m_obArray.RemoveAll();
 CDocument::DeleteContents();
}
另一种方法
 while(nCount--)
 {
  delete m_obArray.GetAt(nCount);
  m_obArray.RemoveAt(nCount);
 }

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/GoOnDrift/article/details/5399535

智能推荐

C语言文件操作相关的函数_c语言与文件处理有关的函数-程序员宅基地

文章浏览阅读865次。文件的打开和关闭文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件 的关系。ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。FILE * fopen ( const char * filename, const char * mode ); int fcl..._c语言与文件处理有关的函数

java 无法读取文件_java 读取文件,无法显示文件内容,如何解决? 谢谢。-程序员宅基地

文章浏览阅读1.1k次。从来没见过进行文件读取写入时,在写入中需要随机数的,你读取文件就是从一个地方获取输入流,然后将这个输入流写到别的地方,根本不要随机数。给你一个示例://copyafiletoanotherfilebyusingFileReader/FileWriterimportjava.io.*;publicclassTFileRead{publicstaticvoidmain(S..._java复制文件文件没有内容显示

vue引入原生高德地图_前端引入原生地图-程序员宅基地

文章浏览阅读556次,点赞2次,收藏3次。由于工作上的需要,今天捣鼓了半天高德地图。如果定制化开发需求不太高的话,可以用vue-amap,这个我就不多说了,详细就看官网 https://elemefe.github.io/vue-amap/#/zh-cn/introduction/install然而我们公司需要英文版的高德,我看vue-amap中好像没有这方面的配置,而且还有一些其他的定制化开发需求,然后就只用原生的高德。其实原生的引入也不复杂,但是有几个坑要填一下。1. index.html注意,引入的高德js一定要放在头部而_前端引入原生地图

ViewGroup重写大法 (一)-程序员宅基地

文章浏览阅读104次。本文介绍ViewGroup重写,我们所熟知的LinearLayout,RelativeLayout,FrameLayout等等,所有的容器类都是ViewGroup的子类,ViewGroup又继承View。我们在熟练应用这些现成的系统布局的时候可能有时候就不能满足我们自己的需求了,这是我们就要自己重写一个容器来实现效果。ViewGroup重写可以达到各种效果,下面写一个简单的重写一个Vi..._viewgroup 重写

Stm32学习笔记,3万字超详细_stm32笔记-程序员宅基地

文章浏览阅读1.8w次,点赞279次,收藏1.5k次。本文章主要记录本人在学习stm32过程中的笔记,也插入了不少的例程代码,方便到时候CV。绝大多数内容为本人手写,小部分来自stm32官方的中文参考手册以及网上其他文章;代码部分大多来自江科大和正点原子的例程,注释是我自己添加;配图来自江科大/正点原子/中文参考手册。笔记内容都是平时自己一点点添加,不知不觉都已经这么长了。其实每一个标题其实都可以发一篇,但是这样搞太琐碎了,所以还是就这样吧。_stm32笔记

CTS(13)---CTS 测试之Media相关测试failed 小结(一)_mediacodec框架 cts-程序员宅基地

文章浏览阅读1.8k次。Android o CTS 测试之Media相关测试failed 小结(一)CTSCTS 即兼容性测试套件,CTS 在桌面设备上运行,并直接在连接的设备或模拟器上执行测试用例。CTS 是一套单元测试,旨在集成到工程师构建设备的日常工作流程(例如通过连续构建系统)中。其目的是尽早发现不兼容性,并确保软件在整个开发过程中保持兼容性。CTS 是一个自动化测试工具,其中包括两个主要软件组件:CTS tra..._mediacodec框架 cts

随便推点

Spark伪分布安装(依赖Hadoop)_下载spark的hadoop依赖-程序员宅基地

文章浏览阅读6.7k次,点赞7次,收藏14次。一、伪分布安装Spark安装环境:Ubuntu 14.04 LTS 64位+Hadoop2.7.2+Spark2.0.0+jdk1.7.0_761、安装jdk1.7(1)下载jdk-7u76-linux-x64.tar.gz;(2)解压jdk-7u76-linux-x64.tar.gz,并将其移动到/opt/java/jdk路径下(自建);命令:tar -zxvf jdk-_下载spark的hadoop依赖

TCP/IP 是用于因特网 (Internet) 的通信协议_广泛应用在internet中的tcp/ip的网络管理主要使用的是 ____协议。 (填空题)-程序员宅基地

文章浏览阅读6.7k次。计算机通信协议计算机通信协议是对那些计算机必须遵守以便彼此通信的规则的描述。什么是 TCP/IP?TCP/IP 是供已连接因特网的计算机进行通信的通信协议。TCP/IP 指传输控制协议/网际协议 (Transmission Control Protocol / Internet Protocol)。TCP/IP 定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准..._广泛应用在internet中的tcp/ip的网络管理主要使用的是 ____协议。 (填空题)

java中的一些经典算法_java中temsize+=1运算-程序员宅基地

文章浏览阅读360次。转自:落尘曦的博客:http://blog.csdn.net/qq_23994787 原文链接:https://blog.csdn.net/qq_23994787/article/details/77951244#_Toc9101经典算法的Java实现(1)河内塔问题: 42(2)费式数列 43(3)巴斯卡(Pascal)三角形 44(4)蒙地卡罗法求 PI 45(..._java中temsize+=1运算

Linux习题简答题_linux中,第一个普通用户的uid为____。-程序员宅基地

文章浏览阅读3.1k次,点赞6次,收藏27次。第一章Q1 简述Linux系统的应用领域 Linux服务器;嵌入式Linux系统;软件开发平台;桌面应用Q2 简述Linux系统的特点 开放性、多用户、多任务、良好的用户界面、设备独立性、丰富的网络功能、可靠的系统安全、良好的可移植性Q3 简述Linux系统的组成 内核、shell、文件系统、应用程序Q4 简述主流的Linux发行版本 Redhat SUSE Oracle CentOS Ubuntu Debian Mandriva Gentoo Slackware Fe_linux中,第一个普通用户的uid为____。

【路径规划】基于matlab粒子群算法新型概率密度无人机作战路径规划【含Matlab源码 2620期】_已知目标出现概率热图matlab无人机路径规划-程序员宅基地

文章浏览阅读183次。粒子群算法新型概率密度无人机作战路径规划完整的代码,方可运行;可提供运行操作视频!适合小白!_已知目标出现概率热图matlab无人机路径规划

navicat执行.sql文件_navicat执行sql文件-程序员宅基地

文章浏览阅读2w次,点赞5次,收藏19次。1、准备好需要执行的.sql文件.sql文件需要注意:每条语句都需要用;作为结束,否则属于语法错误,执行会报错。我们用下面3条语句生成.sql文件测试一下:select SYSDATE() from dual;select COUNT(100) from dual;select CONCAT_WS(' ','test','import','.sql','files');将它保存为import_demo.sql等待测试。2、navicat中选中数据库右键选择.sql文件进行执行选中目标数据库_navicat执行sql文件