孙鑫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

智能推荐

【JZOJ5262】【GDOI2018模拟8.12】树(DP,性质题)_gdoi2018省选模拟树-程序员宅基地

文章浏览阅读460次。DescriptionSolution首先我们可以知道两个性质:1、路径u-v和路径v-w可以合并为路径u-w;2、路径u1-v1加路径u2-v2和路径u1-v2加路径u2-v1是等价的(就是起始点和终点可以互换) 那么知道这些性质之后就很好做了。我们只用知道每个点多少次做起点和多少次做终点。 我们设f[i]表示满足i子树的需求i上的值要是多少。 那么枚举i的所有儿子,判断a[i]-f[i],_gdoi2018省选模拟树

[PTA]7-65 字符串替换 (15 分)含思路_字符串替换pta-程序员宅基地

文章浏览阅读2.8k次,点赞4次,收藏28次。我们进行简单的运算即可实现倒序。_字符串替换pta

linux网络设置_linux如何开启网络连接-程序员宅基地

文章浏览阅读4k次,点赞5次,收藏22次。traceroute 180.101.50.188————————测试到180.101.50.188有多少个网关。vim /etc/sysconfig/static-routes——————————修改。netstat -antp | grep 22———————查看端口号22的相关信息。systemctl restart network————————————重启。systemctl restart network————————重新启动。_linux如何开启网络连接

pr中,视频导入后,视频画面大小显示不完整应该如何解决?_avi视频到pr里会放大-程序员宅基地

文章浏览阅读4w次,点赞23次,收藏6次。本人pr小白,今天编辑视频时候遇到了问题,也解决了,所以分享记录一下。问题一视频下面原来有字幕的,可是导入的视频变大了,现在看不到了怎么办?还有就是,频导入之后画质好像变糊了又是为什么?解决:将箭头放到要编辑的视频那里,右击,然后点击设为帧大小这样完整的视频就出来了。问题二如果视频模糊,就是序列设置的不对 要先新建序列一般的都是1920×1080本人博客:https://blog.csdn.net/weixin_46654114本人b站求关注:https://space.bi_avi视频到pr里会放大

apollo中配置map,list_apollo list-程序员宅基地

文章浏览阅读1.8k次。注:key可以不用引号,value使用单引号,但key中存在_或-等一些特殊字符时,需要加上引号,避免出错。注:key可以不用引号,value也不用引号,但key中存在_或-等一些特殊字符时,需要加上引号,避免出错。注:使用@Value注解获取,apollo中未配置时默认为null。注:使用@Value注解获取,apollo中未配置时默认为null。2.apollo中的Map配置。1.apollo中的Map配置。注:使用逗号分隔,不用引号。..._apollo list

比最快的超级计算机快一百万亿倍!中国科学家实现“量子计算优越性”里程碑_中国科学院比马普所强-程序员宅基地

文章浏览阅读4.4k次,点赞22次,收藏12次。本文来自:中国科学技术大学公众号北京时间12月4日国际顶尖杂志《Science》刊发了中国科学技术大学潘建伟、陆朝阳等组成的研究团队的一项重磅研究成果让我们一起来看看吧!中国科学家实现“量子计算优越性”里程碑中国科学技术大学潘建伟、陆朝阳等组成的研究团队与中科院上海微系统所、国家并行计算机工程技术研究中心合作,构建了76个光子100个模式的量子计算原型机“九章”,实现了具有实用前景的“高斯玻色取样”任务的快速求解。根据现有理论该量子计算系统处理高斯玻色取样的速度比目前最快的超级计算机快一百万._中国科学院比马普所强

随便推点

大数据平台核心技术 学堂在线 雨课堂 第八讲作业答案 人文交流月_vertectorization-程序员宅基地

文章浏览阅读2k次。关于Vertectorization哪些是正确的( )相对于其他编程模型,sql在大数据领域有哪些好处( )哪些部分适合做codegen( )关于内存计算描述不正确的有( )_vertectorization

java汉字拼音简码_java生成首字母拼音简码的总结-程序员宅基地

文章浏览阅读306次。百度找到了某论坛高人写的java(具体论坛记不清了),直接用来调用,再次非常感谢,基本上实现了我的需求package MD5;import java.util.Scanner;public class ChineseToPinYin {/*** 汉字转拼音缩写** @param str* 要转换的汉字字符串* @return String 拼音缩写*/public Strin..._java生成拼音码

C++ 数据结构——堆排序_数据结构堆排序c++-程序员宅基地

文章浏览阅读93次。/* 堆排序 */#include <iostream>using namespace std;int *data;void Sift(int k,int last){ int i,j,temp; i=k;j=2*i+1; while (j<=last) { if(j<last&&data[j]<data[j+1]) j++; if(data[i]>data[j]) _数据结构堆排序c++

debian 11 还不能进入命令行界面,按照网上的改也不行。_debian 无法打开命令行窗口-程序员宅基地

文章浏览阅读952次。再查查资料,有没有DEBIAN问题解答中心呢?_debian 无法打开命令行窗口

2345王牌输入法的卸载_89e1d5c2-a068-44b6-b820-f8406c8a4706-程序员宅基地

文章浏览阅读2.3k次,点赞3次,收藏10次。2345王牌输入法的卸载输入法卸载了也还有2345这个流氓输入法,研究3个小时找到了2345输入法在语言栏的根源所在,希望能帮到你windows键加R键打开运行,输入regedit 然后ctrl+F键 搜索下面路径,打开后就会看见语言栏里的输入法了,直接删除加粗这个文件夹,就删除了HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CTF\TIP{0055AAB0-EACB-46DB-9BB4-1B97FC046D02}\LanguageProfile\0x00000804\ _89e1d5c2-a068-44b6-b820-f8406c8a4706

Android R setenforce 实现_android setenforce-程序员宅基地

文章浏览阅读2.2k次。1、开机启动system/core/init/main.cppint main(int argc, char** argv) {#if __has_feature(address_sanitizer) __asan_set_error_report_callback(AsanReportCallback);#endif if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc,._android setenforce

推荐文章

热门文章

相关标签