How are the parts of the document/view structure associated?

Source: Internet
Author: User
The document/view structure is the most distinctive and difficult part of MFC, this involves different objects such as applications, document templates, documents, views, MDI frame windows, and MDI subwindows. If you do not know how these parts are associated, you may make mistakes, it is difficult to compile a horizontal document/view program. For example, when I was a beginner in VC programming, I added two document templates to the application. The two templates share one document class, but the view is different, it is expected that when the document view of a template changes the document, the view of another document template can be updated after updateallviews is called. Of course, the results will not work, the reason is that you have no in-depth understanding of the documentation/View Structure of MFC. The best way to understand it is to read the source code of MFC. Below are my notes:
  
   (1) Relationship between application objects and document templates:
  
First, there is a common data member m_pdocmanager of the cdocmanager pointer type in the Application object. In cdocmanager, maintain a cptrlist type linked list: m_tempatelist, which is a protection member. The initinstance function calls the cwinapp: adddoctemplate function. It actually calls the adddoctemplate function of m_pdocmanager to add a template pointer to the linked list m_templatelist. Cwinapp provides the getfirstdoctemplateposition and getnextdoctemplate functions to access the m_templatelist linked list (in fact, cdocmanager functions are called ).
  
In File Operations, cwinapp provides the most common functions: onfilenew and onfileopen. It also calls the Same Name function of the cdocmanager class. Generally, when there is only one document template, a blank file is created. If there are multiple document templates, a dialog box is displayed, prompting you to select the document type. Its source code is as follows:
  
Void cdocmanager: onfilenew ()
  
{
  
If (m_templatelist.isempty ())
  
{
  
.......
  
Return;
  
}
  
// Get the pointer of the first document template
  
Cdoctemplate * ptemplate = (cdoctemplate *) m_templatelist.gethead ();
  
If (m_templatelist.getcount ()> 1)
  
{
  
// If there is more than one document template, a dialog box appears prompting you to select
  
Cnewtypedlg DLG (& m_templatelist );
  
Int nid = DLG. domodal ();
  
If (nid = idok)
  
Ptemplate = DLG. m_pselectedtemplate;
  
Else
  
Return; // none-cancel Operation
  
}
  
......
  
// When the parameter is null, OpenDocument file creates a new file.
  
Ptemplate-> opendocumentfile (null );
  
}
  
Open the file:
  
Void cdocmanager: onfileopen ()
  
{
  
// The open file dialog box appears.
  
Cstring newname;
  
If (! Dopromptfilename (newname, afx_ids_openfile,
  
Ofn_hidereadonly | ofn_filemustexist, true, null ))
  
Return; // open canceled
  
Afxgetapp ()-> opendocumentfile (newname); // actually calls the function with the same name as the document template
  
}
  
   (2) links between document templates and documents:
It can be seen from the above that the application object's file creation and opening relies on the opendocumentfile function of the document template. The template class of MFC is used to contact the document class, View class, and framework class. In its constructor, the following information is required:
  
Cdoctemplate (uint nidresource, cruntimeclass * pdocclass, cruntimeclass * pframeclass, cruntimeclass * pviewclass );
  
The constructor uses the last three parameters to assign values to the protection members of the three cruntimeclass * types:
  
M_pdocclass = pdocclass;
  
M_pframeclass = pframeclass;
  
M_pviewclass = pviewclass;
  
There are two types of document templates: single document templates and multi-document templates. The implementation of these two templates is different. Apart from the preceding three members, there are different but important member variables. For multi-document templates: cptrlist m_doclist;, single-Document Template: cdocument * m_ponlydoc ;. They all have a member function adddocument, which assigns values to their respective members, in the cdoctemplate of their parent class, values are assigned to the m_pdoctemplate variable of the document it adds as the template's own address:
  
Void cdoctemplate: adddocument (cdocument * pdoc)
  
{
  
Assert_valid (pdoc );
  
Assert (pdoc-> m_pdoctemplate = NULL );
  
Pdoc-> m_pdoctemplate = this;
  
}
  
Since a single document template can only have one document, it only maintains a pointer to its own template: m_ponlydoc. The adddocument function is to assign a value to this member:
  
Void csingledoctemplate: adddocument (cdocument * pdoc)
  
{
  
......
  
Cdoctemplate: adddocument (pdoc );
  
M_ponlydoc = pdoc;
  
}
Since a multi-document template can have multiple documents, it must maintain a linked list containing pointers to all the documents it opens. Therefore, its adddocument implementation is:
  
Void cmultidoctemplate: adddocument (cdocument * pdoc)
  
{
  
......
  
Cdoctemplate: adddocument (pdoc );
  
M_doclist .. addtail (pdoc );
  
}
The template uses m_ponlydoc (single document) or remembers the pointers of all the templates it owns, And the getfirstdocposition and getnextdoc functions can be used to access the documents it owns, at the same time, the document remembers the pointer of the template to which it belongs, and the document provides the getdoctemplate () function to obtain the template to which it belongs.
  
The adddocument function is called mainly in the createnewdocument function of another member function. Its function is to create a new document:
  
Cdocument * cdoctemplate: createnewdocument ()
  
{
  
If (m_pdocclass = NULL)
  
{
  
......
  
}
  
Cdocument * pdocument = (cdocument *) m_pdocclass-> Createobject ();
  
......
  
Adddocument (pdocument );
  
Return pdocument;
  
}
  
The createnewdocument function mainly uses the Createobject function of the runtime pointer of the document class to create a new document object, and uses adddocument to assign its pointer to relevant members for future use.
  
Both the onfilenew and onfileopen functions of the application use the opendocumentfile function of the template, and most of them use this function during actual programming. In the msdn document, the function opens the file when the parameter is not null. Otherwise, the createnewdocument function mentioned above will be used to create a new document. How can this function be implemented?
  
Cdocument * csingledoctemplate: opendocumentfile (lpctstr lpszpathname,
  
Bool bmakevisible)
  
{
  
Cdocument * pdocument = NULL;
  
Cframewnd * pframe = NULL;
  
Bool bcreated = false; // => Doc and frame created
  
Bool bwasmodified = false;
  
// If an opened document exists, the system will ask whether to save the file.
  
If (m_ponlydoc! = NULL)
  
{
  
Pdocument = m_ponlydoc;
  
If (! Pdocument-> savemodified ())
  
Return NULL;
  
Pframe = (cframewnd *) afxgetmainwnd ();
  
......
  
}
  
// Create a new file
  
Else
  
{
  
Pdocument = createnewdocument ();
  
Assert (pframe = NULL );
  
Bcreated = true;
  
}
  
......
  
// If you create a document for the first time, you also need to create a framework window.
  
If (pframe = NULL)
  
{
  
Assert (bcreated );
  
// Create frame-set as main document frame
  
Bool bautodelete = pdocument-> m_bautodelete;
  
Pdocument-> m_bautodelete = false;
  
Pframe = createnewframe (pdocument, null );
  
Pdocument-> m_bautodelete = bautodelete;
  
......
  
}
  
If (lpszpathname = NULL)
  
{
  
// Set the default title for the new document
  
Setdefatitle title (pdocument );
  
......
  
// In general, the onnewdocument is reloaded to initialize some data. If false is returned, the initialization is lost/failed, and the destruction window is displayed.
  
If (! Pdocument-> onnewdocument ())
  
{
  
......
  
If (bcreated)
  
Pframe-> destroywindow (); // will destroy document
  
Return NULL;
  
}
  
}
  
Else
  
{
  
Cwaitcursor wait;
  
// Open an existing document
  
Bwasmodified = pdocument-> ismodified ();
  
Pdocument-> setmodifiedflag (false );
  
// The onopendocument function reinitializes the Document Object.
  
If (! Pdocument-> onopendocument (lpszpathname ))
  
{
  
If (bcreated)
  
{
  
// Document creation
  
Pframe-> destroywindow ();
  
}
  
Else if (! Pdocument-> ismodified ())
  
{
  
// No documentation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.