深入浅出MFC文档/视图架构之文档(1)

编程之家收集整理的这篇文章主要介绍了深入浅出MFC文档/视图架构之文档(1)编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
 1、文档类CDocument

  在"文档/视图"架构的MFC程序中,文档是一个CDocument派生对象,它负责存储应用程序的数据,并把这些信息提供给应用程序的其余部分。CDocument类对文档的建立及归档提供支持并提供了应用程序用于控制其数据的接口,类CDocument的声明如下:

/
// class CDocument is the main document data abstraction
class CDocument : public CCmdTarget
{
 DECLARE_DYNAMIC(CDocument)
public:
 // Constructors
 CDocument();

 // Attributes
public:
 const CString& GetTitle() const;
 virtual void SetTitle(LPCTSTR lpszTitle);
 const CString& GetPathName() const;
 virtual void SetPathName(LPCTSTR lpszPathName,BOOL bAddToMRU = TRUE);

 CDocTemplate* GetDocTemplate() const;
 virtual BOOL IsModified();
 virtual void SetModifiedFlag(BOOL bModified = TRUE);

 // Operations
 void AddView(CView* pView);
 void RemoveView(CView* pView);
 virtual POSITION GetFirstViewPosition() const;
 virtual CView* GetNextView(POSITION& rPosition) const;

 // Update Views (simple update - DAG only)
 void UpdateAllViews(CView* pSender,LPARAM lHint = 0L,
 CObject* pHint = NULL);

 // Overridables
 // Special notifications
 virtual void OnChangedViewList(); // after Add or Remove view
 virtual void DeleteContents(); // delete doc items etc

 // File helpers
 virtual BOOL OnNewDocument();
 virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
 virtual BOOL OnSaveDocument(LPCTSTR lpszPathName);
 virtual void OnCloseDocument();
 virtual void ReportSaveLoadException(LPCTSTR lpszPathName,
 CException* e,BOOL bSaving,UINT nIDPDefault);
 virtual CFile* GetFile(LPCTSTR lpszFileName,UINT nOpenFlags,
 CFileException* pError);
 virtual void ReleaseFile(CFile* pFile,BOOL bAbort);

 // advanced overridables,closing down frame/doc,etc.
 virtual BOOL CanCloseFrame(CFrameWnd* pFrame);
 virtual BOOL SaveModified(); // return TRUE if ok to continue
 virtual void PreCloseFrame(CFrameWnd* pFrame);

 // Implementation
protected:
 // default implementation
 CString m_strTitle;
 CString m_strPathName;
 CDocTemplate* m_pDocTemplate;
 CPtrList m_viewList; // list of views
 BOOL m_bModified; // changed since last saved

public:
 BOOL m_bAutoDelete; // TRUE => delete document when no more views
 BOOL m_bEmbedded; // TRUE => document is being created by OLE

 #ifdef _DEBUG
  virtual void Dump(CDumpContext&) const;
  virtual void AssertValid() const;
 #endif //_DEBUG
 virtual ~CDocument();

 // implementation helpers
 virtual BOOL DoSave(LPCTSTR lpszPathName,BOOL bReplace = TRUE);
 virtual BOOL DoFileSave();
 virtual void UpdateFrameCounts();
 void DisconnectViews();
 void SendInitialUpdate();

 // overridables for implementation
 virtual HMENU GetDefaultMenu(); // get menu depending on state
 virtual HACCEL GetDefaultAccelerator();
 virtual void OnIdle();
 virtual void OnFinalRelease();

 virtual BOOL OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo);
 friend class CDocTemplate;

protected:
 // file menu commands
 //{{AFX_MSG(CDocument)
  afx_msg void OnFileClose();
  afx_msg void OnFileSave();
  afx_msg void OnFileSaveAs();
 //}}AFX_MSG
 // mail enabling
 afx_msg void OnFileSendMail();
 afx_msg void OnUpdateFileSendMail(CCmdUI* pCmdUI);
 DECLARE_MESSAGE_MAP()
};

  一个文档可以有多个视图,每一个文档都维护一个与之相关视图的链表(CptrList类型的 m_viewList实例)。CDocument::AddView将一个视图连接到文档上,并将视图的文档指针指向该文档:

void CDocument::AddView(CView* pView)
{
 ASSERT_VALID(pView);
 ASSERT(pView->m_pDocument == NULL); // must not be already attached
 ASSERT(m_viewList.Find(pView,NULL) == NULL); // must not be in list

 m_viewList.AddTail(pView);
 ASSERT(pView->m_pDocument == NULL); // must be un-attached
 pView->m_pDocument = this;

 OnChangedViewList(); // must be the last thing done to the document
}

  CDocument::RemoveView则完成与CDocument::AddView相反的工作:

void CDocument::RemoveView(CView* pView)
{
 ASSERT_VALID(pView);
 ASSERT(pView->m_pDocument == this); // must be attached to us

 m_viewList.RemoveAt(m_viewList.Find(pView));
 pView->m_pDocument = NULL;

 OnChangedViewList(); // must be the last thing done to the document
}

  从CDocument::AddView和CDocument::RemoveView函数可以看出,在与文档关联的视图被移走或新加入时CDocument::OnChangedViewList将被调用

void CDocument::OnChangedViewList()
{
 // if no more views on the document,delete ourself
 // not called if directly closing the document or terminating the app
 if (m_viewList.IsEmpty() && m_bAutoDelete)
 {
  OnCloseDocument();
  return;
 }

 // update the frame counts as needed
 UpdateFrameCounts();
}

  CDocument::DisconnectViews将所有的视图都与文档"失连":

void CDocument::DisconnectViews()
{
 while (!m_viewList.IsEmpty())
 {
  CView* pView = (CView*)m_viewList.RemoveHead();
  ASSERT_VALID(pView);
  ASSERT_KINDOF(CView,pView);
  pView->m_pDocument = NULL;
 }
}

  实际上,类CDocument对视图的管理与类CDocManager对文档模板的管理及CDocTemplate对文档的管理非常类似,少不了的,类CDocument中可遍历对应的视图(出现GetFirstXXX和GetNextXXX两个函数):

POSITION CDocument::GetFirstViewPosition() const
{
 return m_viewList.GetHeadPosition();
}

CView* CDocument::GetNextView(POSITION& rPosition) const
{
 ASSERT(rPosition != BEFORE_START_POSITION);
 // use CDocument::GetFirstViewPosition instead !
 if (rPosition == NULL)
  return NULL; // nothing left
 CView* pView = (CView*)m_viewList.GetNext(rPosition);
 ASSERT_KINDOF(CView,pView);
 return pView;
}

  CDocument::GetFile和CDocument::ReleaseFile函数完成对参数lpszFileName指定文档的打开与关闭操作:

CFile* CDocument::GetFile(LPCTSTR lpszFileName,
CFileException* pError)
{
 CMirrorFile* pFile = new CMirrorFile;
 ASSERT(pFile != NULL);
 if (!pFile->Open(lpszFileName,nOpenFlags,pError))
 {
  delete pFile;
  pFile = NULL;
 }
 return pFile;
}

void CDocument::ReleaseFile(CFile* pFile,BOOL bAbort)
{
 ASSERT_KINDOF(CFile,pFile);
 if (bAbort)
  pFile->Abort(); // will not throw an exception
 else
  pFile->Close();
 delete pFile;
}

  CDocument类的OnNewDocument、OnOpenDocument、OnSaveDocument及OnCloseDocument这一组成员函数用于创建、打开、保存或关闭一个文档。在这一组函数中,上面的CDocument::GetFile和CDocument::ReleaseFile两个函数得以调用

BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)
{
 if (IsModified())
  TRACE0("Warning: OnOpenDocument replaces an unsaved document./n");

 CFileException fe;
 CFile* pFile = GetFile(lpszPathName,
 CFile::modeRead|CFile::shareDenyWrite,&fe);
 if (pFile == NULL)
 {
  ReportSaveLoadException(lpszPathName,&fe,FALSE,AFX_IDP_Failed_TO_OPEN_DOC);
  return FALSE;
 }

 DeleteContents();
 SetModifiedFlag(); // dirty during de-serialize

 CArchive loadArchive(pFile,CArchive::load | CArchive::bNoFlushOnDelete);
 loadArchive.m_pDocument = this;
 loadArchive.m_bForceFlat = FALSE;
 TRY
 {
  CWaitCursor wait;
  if (pFile->GetLength() != 0)
   Serialize(loadArchive); // load me
   loadArchive.Close();
   ReleaseFile(pFile,FALSE);
 }
 CATCH_ALL(e)
 {
  ReleaseFile(pFile,TRUE);
  DeleteContents(); // remove Failed contents

  TRY
  {
   ReportSaveLoadException(lpszPathName,e,AFX_IDP_Failed_TO_OPEN_DOC);
  }
  END_TRY
  DELETE_EXCEPTION(e);
  return FALSE;
 }
 END_CATCH_ALL

 SetModifiedFlag(FALSE); // start off with unmodified

 return TRUE;
}

总结

以上是编程之家为你收集整理的深入浅出MFC文档/视图架构之文档(1)全部内容,希望文章能够帮你解决深入浅出MFC文档/视图架构之文档(1)所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您喜欢寻找一群志同道合、互帮互助的学习伙伴,可以点击下方链接加入:
编程之家官方1群:1065694478(已满)
编程之家官方2群:163560250(已满)
编程之家官方3群:312128206

相关文章

猜你在找的C&C++相关文章

c++的基本类型包括char,short,int,long,lang lang(C++新增的),double,float,boo各种类型占用内存大小问题,sizeof和strlen的区别,有无符号类型之间运算情况,.有无符号类型之间的转换,为什么会出现结果数值异常大,为什么浮点数没有分有无符号类型
浮点数的精度问题和有效范围大小,还是有些东西没有说出来,我觉得还是应该说一说,我们常说的单精度有6 ~ 7位的有效范围,而双精度有15 ~ 16位的有效范围,这里所指的有效范围并不是该数值的大小,这是很多初学者的一个误区,并不是说这个单精度的float只能存储6 ~ 7位怎么大的数,如果是1234578这样的数则无法存储,这是错误的,想要理解这里的有效范围,还需要知道浮点数的存储方法,浮点数使用科学记数法来表示存储的,最大可以达到3.4E38,这是一个很大的数,达到了38位之多,显然不是上面所说的6 ~
文章目录0. 目前遇到的cout和cin的特性1. 字符和字符串2. 输入输出字符串接收数据情况3. 结构体4. 共用5. 枚举6. 基本类型组合而成的复合类型7. 静态数组和动态数组(需要创建指针)8. 字符和字符串想要使用cout输出两个字符数组,第二个被正常输出,第一个正常输出后出现了乱码,处理字符串的函数,像cout输出字符串,它们都会把字符串里面的字符一个一个的进行处理,如果遇到空字符,则停止处理,由于第一种写法没有写入3. 结构体声明结构体使用struct关键字,创建形式如下:...
cin是C++的标准输入流对象,主要用于从标准输入读取数据,无论字符型,浮点型,还是整数形变量,我们只需要cin>>变量名称;即可完成各类数据读取数据。说到这里就不得不提到C语言中的标准输入函数scanf(),对于刚学习C++的萌新,一定会惊艳到相对于scanf函数,cin带来的便捷,scanf每次想要读取数据,必须指定数据类型,这显然显的有些繁琐。那么,为什么单靠一个cin>>变量名称,即可确定数据类型并读取数据,这其中的奥秘被隐藏在这个>>运算符之中,这个运算符叫做流提取符,其实cin>>的原型是cin
前面学习字符串的时候简单说了string字符串和C风格字符串的不同,今天来详细的学习一下string字符串过去学习C的时候,想要使用字符串应该是如下的格式:char a[] = "hello world"; //这里省略了,但编译器会我们自动添加并隐藏再字符串初始化,赋值,拼接,附加字符串长度的函数
很多人,包括我,看书,看完一章怎么怎么的,然后不管是作业,还是考试出现这一章的内容,总有些地方跟我们脑袋里面理解的不一样,自己明明学习过,但机器给出的答案和自己的完全相反,或者完全不正确,这就是为什么书读百遍,其义自见,可能夸张了,不知道你们是怎样的,一本书多读,确实能带给我不同的知识,这也是我为什么想起来写总结,我加了一个群,看到萌新们问的问题大多是他们看书漏掉的知识,这些人一定是只看了一遍或者没看,他们的程序刚好需要那么一点小小的知识去解决,可是他们不知道这一点小小的知识。
以前就遇到函数参数是指针,想要修改指针,结果总是不理想,前几天群里也是有萌新问到这个问题,刚好我当时在书上看到怎么一句话:==函数参数是按值传递和按引用传递==,瞬间就顿悟了这个问题。这是以前发现问题时写的,只写了解决方法,并没有说明其中原因,其实是当时还是不知原因的,俗话说:知其然,知其所以然,刚好顿悟了这个原因,就记录一下下吧,文章想到最后,感觉做一个图比较有
1.数组越界造成的死循环2.int main(int argc,char* argv[])里面的参数有什么作用?3.程序代码区、文字常量区、静态区(全局区)、堆区、栈区4.函数指针 指针函数 指针数组 数组指针 傻傻分不清5.return continue break return 0 exit6.最大值加1等于最小值?(一图看懂)7.精度问题
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注