MFC single document / view structure poor chase
table of Contents
Chapter 1 Retrieves WinMain Functions 2 Chapter 2 InitApplication () Function 2 Chapter 3 InitInstance () Function 3 Section 1: New CsingLeDectemplate 3 2: Addd IndocTemplate (PdoCtemplate); 5 Section 3: ProcessShellcommand (cmdinfo) The first paragraph AFXGetApp () -> oncmdmsg (...) 6 Section 2 ONFileNew (); 6 Section 4: m_pmainwnd-> showwindow (sw_show); /// Display window 8 Section 5: m_pmainwnd-> UpdateWindow (); /// Heavy painting window 8 Chapter 4 PAPP-> RUN function 8 Chapter 5 summary 8
This article will describe the MFC's document / view structure for a single document. He directly opens the source code of the MFC to analyze, and the independent part is removed during the analysis. So the first step is to create a single document, which is a single document, which will be around this project. The first chapter retrieves the WinMain function First find the Winmain.cpp file in the VC installation path, the AFXWINMAIN function is the entrance to the VC compiler, removes some unimportant things, get the procedure. INT AFXAPI AFXWINMAIN (Hinstance Hinstance, LPTSTR LPCMDLINSTANCE, INT NCMDSHOW) {INT NRETURNCODE = -1; CWINAPP * PAPP = AFXGetApp (); /// Gets the application class's pointer is independent of the document view. AfxWininit (Hinstance, Hprevinstance, LPCMDline, ncmdshow); // /// is not related to the document view. PAPP-> initApplication (); // The initialization application is shown below. PAPP-> InitInstance (); /// Most Imprinted NRETURNCODE = PAPP-> Run (); /// The message is looped until the application is turned off. Unrelated to the document view. AFXWINTERM (); /// is not related to the document view. Return nreturNCode; /// The entire application ends. } The following steps are described. Chapter II INITAPPLICATION () Function In the file appcore.cpp file InitApplication as follows: BOOL CWINAPP :: INitApplication () {if (cdocmanager :: pstaticDocmanager! = Null) // This paragraph is not big, it is not reasonable, temporarily ignore it {IF (m_pdocmanager == null) m_pdocmanager = cdocmanager :: PStaticDocManager; cdocmanager :: pstaticdocmanager = null;}
IF (m_pdocmanager! = null) m_pdocmanager-> adddoctemplate (null); else cdocmanager :: bStaticinit = false; / * Our program will execute, indicating that document class is created dynamically, that is, using runtime_class to create (See below). * / Return true;} Description: The CDOCManager class is an undisclosed class. He is mainly used to manage multi-document template objects. This class is not very important for single document only one document template, but still manages document templates; This article is only instructions on the relevant Bstaticinit is a static member. The InitInstance Chapter () function which generally is overloaded, the First project, and the InitInstance classes related document view some of the following procedures: CSingleDocTemplate * pDocTemplate; /// defined pointer pDocTemplate = new CSingleDocTemplate (IDR_MAINFRAME, RUNTIME_CLASS ( CfirstDoc), runtime_class (cmainframe), runtime_class (cfirstView)); /// The role of this statement is found in the first addDDOCTemplate (PDOCTemplate);
CCommandLineInfo cmdinfo; // defines an object PARSECMMAVANDLINE (CMDInfo); // / Analyze the command line and send parameters, regardless of the document view
If (! ProcessShellcommand (cmdinfo)) /// This is the most important detailed three-segment return false;
m_pmainwnd-> showwindow (sw_show); /// Display window m_pmainwnd-> UpdateWindow (); first: new csingleDoctemplateNew CSINGEDEDEMPLATE is actually a CSINGLEDEMPLATE object and calling his constructor, you must clear this sentence, you must first understand RUNTIME_CLASS structure, RUNTIME_CLASS structure is defined as follows: #define RUNTIME_CLASS (class_name) ((CRuntimeClass *) (& class_name :: class ## class_name)) so after these words unfold as follows (about ## in line with the specific meaning see MSDN): pDocTemplate = new CSingleDocTemplate (IDR_MAINFRAME, (CRuntimeClass *) (& CFirstDoc :: classCFirstDoc), (CRuntimeClass *) (& CMainFrame :: classCMainFrame), (CRuntimeClass *) (& CFirstView :: classCFirstView)); then we will find CfirstDoc, CmainFrame, CfirstView each I will take more static members. Where is it? To view the definition of these three classes We will find that each class definition has a macro Declare_DyncReate, which has another macro IMPLEMENT_DYNCREATE in the implementation file. The unfolding of these macros is listed below: (1) Document class declare_dyncreate (cfirstdoc) is expanded to: public: static const cruntimeclass classcfirstdoc; /// This is the static member Virtual Cruntimeclass * GtruntimeClass () Constims * GetRuntimeClass () Constim ; static CObject * PASCAL CreateObject (); after IMPLEMENT_DYNCREATE (CFirstDoc, CDocument) expands to: CObject * PASCAL CFirstDoc :: CreateObject () {return new CFirstDoc;} const CRuntimeClass CFirstDoc :: classCFirstDoc = { "CFirstDoc", sizeof (class CFirstDoc ), 0xFFFF, CFirstDoc :: CreateObject, (CRuntimeClass *) (& CDocument :: classCDocument), NULL}; CRuntimeClass * CFirstDoc :: GetRuntimeClass () const {return (CRuntimeClass *) (& CFirstDoc :: classCFirstDoc);} (2) view After the class declare_dyncreate (cfirstView) is expanded to: public: static const cruntimeclass classcfirstview; virtual cruntimeclass * getRuntimeclass () const; static cobject * pascal createObject ();
After IMPLEMENT_DYNCREATE (CFirstView, CView) expands to: CObject * PASCAL CFirstView :: CreateObject () {return new CFirstView;} const CRuntimeClass CFirstView :: classCFirstView = { "CFirstView", sizeof (class CFirstView), 0xFFFF, CFirstView :: CreateObject, (CRuntimeClass *) (& CView :: classCView), NULL}; () const {return (CRuntimeClass *) (& CFirstView :: classCFirstView) CRuntimeClass * CFirstView :: GetRuntimeClass; after} (3) main frame class DECLARE_DYNCREATE (CMainFrame) expand is: public: static const CRuntimeClass classCMainFrame; virtual CRuntimeClass * GetRuntimeClass () const; static CObject * PASCAL CreateObject (); after IMPLEMENT_DYNCREATE (CMainFrame, CFrameWnd) expands to: CObject * PASCAL CMainFrame :: CreateObject () {return new CMainFrame;} const CRuntimeClass CMainFrame :: classCMainFrame = { "CMainFrame", sizeof (class CMainFrame), 0xFFFF, CMainFrame :: CreateObject, (CRuntimeClass *) (& CFrameWnd :: classCFrameWnd), NULL}; CRuntimeClass * CMainFrame :: GetRuntimeClass () const { Return (CRUNTIMECLASS *) (& CMAINFRAME :: Classcm Ainframe);
These macros first define a static variable named in the Class class name in your definition file. Then define a function getRuntimeClass that returns this static variable and implements it in the implementation file. Finally define and implement a function creteObject for creating an object.
Well, we now look at an object constructor CSingleDocTemplate done: Here is his realization CSingleDocTemplate :: CSingleDocTemplate (UINT nIDResource, CRuntimeClass * pDocClass, CRuntimeClass * pFrameClass, CRuntimeClass * pViewClass): CDocTemplate (nIDResource, pDocClass , pframeclass, pviewclass) {m_ponlydoc = null;} It mainly initializes his parent class cdoctemplate, what is CDOCTemplate? As follows: {<1> The address of the three CRUNTIMECLASS structures of the three CRUNTIMECLASS structures of the resource ID and the document, the framework, and the four parameters of the four parameters are saved. <2> loadTemplate (); /////> Loading resources for the specified document template object} This new statement is finally finished. Section II: AddDocTemplate (pDocTemplate); Here is his realization of function void CWinApp :: AddDocTemplate (CDocTemplate * pTemplate) {if (m_pDocManager == NULL) m_pDocManager = new CDocManager; / * Create a document management class, often for a single document Only one document template is not very important to use CDOCManager classes. We can ignore this * / m_pdocmanager-> adddoctemplate (PTEMPLATE); / * Save the document template pointer in the CDOCManager instance to manage him, we just know this Just line * /} Section III: ProcessShellcommand (cmdinfo) This function sent by this function is other than him, in fact, all document classes, frame classes, and view classes are created in this function, in the first The application class has been mentioned in the application class to save the CruntimeClass of the three classes, and the specific function of the CruntimeClass structure refers to the MSDN in accordance with the specific functions of the CRUNTIMECLASS structure.
ProcessShellCommand described as follows: BOOL CWinApp :: ProcessShellCommand (CCommandLineInfo & rCmdInfo) {BOOL bResult = TRUE; switch (rCmdInfo.m_nShellCommand) {case CCommandLineInfo :: FileNew: if (AfxGetApp () -> OnCmdMsg (ID_FILE_NEW, 0, NULL, NULL)! ) Onfilenew (); if (m_pmainwnd == null) BRESULT = false; Break; Case CCommandLineInfo :: FileOpen: if (! OpenDocumentfile (rcmdinfo.m_strfilename) BRESULT = False; Break; ............................ ......// There are also many messages to handle} Return BRESULT;} Participation AFXGetApp () -> oncmdmsg (...) AFXGetApp () -> oncmdmsg is mainly distributed to send command messages, and our relationship is the biggest message is a menu Command ID_FILE_NEW, following the other's handleNew () onfilenew (); OnFileNew just simply calls the same name function for the document management object, his description is as follows: void cwinapp :: onfilenew () {i (m_pdocmanager! = Null) M_PDOCManager -> OnFileNew (); /// CDocManager :: OnFileNew} simply calls the document management class OnFileNew remove some useless after something to achieve the following: void CDocManager :: OnFileNew () {CDocTemplate * pTemplate = (CDocTemplate *) m_templateList.GetHead (); / * Get the first document template, only one document template * / if (m_templatelist.getcount ()> 1) /// {CNEWTYPEDLG DLG (& M_TemplateList); int NID = dlg.domodal (); if (NID == iDok) pTemplate = dlg.m_pSelectedTemplate; else return; /// none - cancel operation} pTemplate-> OpenDocumentFile (NULL); / * actually call the following function CSingleDocTemplate :: OpenDocumentFile Cheung said here, since this function CDocTemplate class is a pure Define function * /} Next, PTEMPLATE-> OpenDocumentFile (NULL); this function, this is the most important function, he has implemented the following six steps:
<1> pDocument = createNewDocument (); // / creation a new document {cdocument * pdocument = (cdocument *) m_pdocclass-> createObject (); / * This is true to create a document object, the document object created here is above Runtime_class (cfirstdoc), the object this is a method of creating an object when the MFC developer is thinking, it should be said that it is better, I don't know how C Builder is constructed. * / AddDocument; /// Record the created object pointer and use it later. } <2> Pframe = CreateNewFrame (pDocument, null); / * Create a new document framework according to the new document pointer, this more important next paragraph Description * / <3> setfaulttitle (pdocument); /// Setting the default title, not important <4> pDocument-> OnnewDocument () /// Clear old document content {deleteContents (); ////> Delete the original content regardless of whether the storage setModifiedFlag (false); /// Clear the once modified tag} <5 > pthread-> m_pmainwnd = pframe; /// Frame window As the pointer of the main window <.6> initialupdateframe (PFrame, PDocument, Bmakevisible); / * Make the view window in the frame to accept OnInitialUpdat, and make Original update. * /
The ONFileNew function of this first paragraph is finally finished. Here to talk <2> CreateNewFrame function CreateNewFrame CDocTemplate member function is as follows three steps: <2.1> CCreateContext context; /// create an object that is the source of our CcreateContext LoadFrame overloaded function that CcreateContext of * / context.m_pCurrentFrame = pOther. ; // / Save the current framework, generally nullcontext.m_pcurrentdoc = pdoc; /// save document object pointer Context.m_pnewViewClass = m_pviewclass; /// save view object pointer Context.m_pnewDoCtemplate = this; /// Save document template pointer . <2.2> CFrameWnd * pFrame = (CFrameWnd *) m_pFrameClass-> CreateObject (); /// real framework to create an object of <2.3> pFrame-> LoadFrame (m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, & context) /// load resources, This is the most important, following {<2.3.1> geticonWndClass (DWDEFAULTSTYLE, NIDRESOURCE) /// Load Resources and register the window {AFXFINDRESOTHANDLE:: Loadicon // / Load Cursor Resource CreateStruct CS; // Create a CREATESTRUCT Structure Example PrecreateWindow (CS); / * Call the window prerequisite function, this function we can overload according to the CS call AFXREGISTERWNDCLASS registration frame window * /} <2.3.2> CREATE (...) // creation frame window, afterwards, I don't talk about it here. <2.3.3> m_hmenudefault = :: getMenu (m_hwnd); /// Get and save the menu handle <2.3.4> loading (nidResource)); /// Load Acceleration Key Table} Tell the Create function below, as follows 4 Steps: <2.3.2.1> HMENU = :: loadMenu (Hinst, lpszMenuname); /// load menu <2.3.2.2> createStruct cs; /// created a CREATESTRUCT structure instance cs.lpcreateParams = lpparam; /// ( At this time, LPPARAM is the CONTEXT object pointer built by <2.3.2.3> PrecreateWindow (CS); /// Call the window preform function, this function we can overload, and call <2.3.2.4> call API functions :: CREATEWINDOWEX really creates a frame window, and WM_CREATE and WM_NCCREATE are issued during creation.