1. 程式人生 > >MFC OnFileNew OnFileOpen過程分析程式碼(一)

MFC OnFileNew OnFileOpen過程分析程式碼(一)

原文:http://blog.csdn.net/teleinfor/article/details/1856725

對OnFileNew()/OnFileOpen()的MFC程式碼跟蹤簡析,簡析可能也談不上了,為了快速的理解MFC的實現思路以及文件檢視架構的應用,在學習的過程當中我也沒有進行學習理解的註解。不過細細閱讀整個的實現流程,相信你我都能理解掌握MFC的整體思路。以後有機會再進行註解吧。

文件的建立順序

 

 

 

A) OnFileNew()執行過程分析

1.     void CWinApp::OnFileNew()

{

       if (m_pDocManager != NULL)

              m_pDocManager->OnFileNew();

}

註釋:MFCID_FILE_NEW選單的響應函式,系統預設操作.

2.     void CDocManager::OnFileNew()

{

       if (m_templateList.IsEmpty())

       {

              TRACE0("Error: no document templates registered with CWinApp./n");

              AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

              return;

       }

 

       CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();

       if (m_templateList.GetCount() > 1)

       {

              // more than one document template to choose from

              // bring up dialog prompting user

              CNewTypeDlg dlg(&m_templateList);

              int nID = dlg.DoModal();

              if (nID == IDOK)

                     pTemplate = dlg.m_pSelectedTemplate;

              else

                     return;     // none - cancel operation

       }

 

       ASSERT(pTemplate != NULL);

       ASSERT_KINDOF(CDocTemplate, pTemplate);

 

       pTemplate->OpenDocumentFile(NULL);

              // if returns NULL, the user has already been alerted

}

:如果跳過此函式而手動操作直接進入pTemplate->OpenDocumentFile(),那麼文件模版列表選擇對話方塊也就不會出現了.

3.     CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)

{

       CDocument* pDocument = CreateNewDocument();

       if (pDocument == NULL)

       {

              TRACE0("CDocTemplate::CreateNewDocument returned NULL./n");

              AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

              return NULL;

       }

       ASSERT_VALID(pDocument);

 

       BOOL bAutoDelete = pDocument->m_bAutoDelete;

       pDocument->m_bAutoDelete = FALSE;   // don't destroy if something goes wrong

       CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);

       pDocument->m_bAutoDelete = bAutoDelete;

       if (pFrame == NULL)

       {

              AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

              delete pDocument;       // explicit delete on error

              return NULL;

       }

       ASSERT_VALID(pFrame);

 

       if (lpszPathName == NULL)

       {

              // create a new document - with default document name

              SetDefaultTitle(pDocument);

 

              // avoid creating temporary compound file when starting up invisible

              if (!bMakeVisible)

                     pDocument->m_bEmbedded = TRUE;

 

              if (!pDocument->OnNewDocument())

              {

                     // user has be alerted to what failed in OnNewDocument

                     TRACE0("CDocument::OnNewDocument returned FALSE./n");

                     pFrame->DestroyWindow();

                     return NULL;

              }

 

              // it worked, now bump untitled count

              m_nUntitledCount++;

       }

       else

       {

              // open an existing document

              CWaitCursor wait;

              if (!pDocument->OnOpenDocument(lpszPathName))

              {

                     // user has be alerted to what failed in OnOpenDocument

                     TRACE0("CDocument::OnOpenDocument returned FALSE./n");

                     pFrame->DestroyWindow();

                     return NULL;

              }

              pDocument->SetPathName(lpszPathName);

       }

 

       InitialUpdateFrame(pFrame, pDocument, bMakeVisible);

       return pDocument;

}

4.     CDocument* CDocTemplate::CreateNewDocument()

{

       // default implementation constructs one from CRuntimeClass

       if (m_pDocClass == NULL)

       {

              TRACE0("Error: you must override CDocTemplate::CreateNewDocument./n");

              ASSERT(FALSE);

              return NULL;

       }

       CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();

       if (pDocument == NULL)

       {

              TRACE1("Warning: Dynamic create of document type %hs failed./n",

                     m_pDocClass->m_lpszClassName);

              return NULL;

       }

       ASSERT_KINDOF(CDocument, pDocument);

       AddDocument(pDocument);

       return pDocument;

}

 

5.     CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)

{

       if (pDoc != NULL)

              ASSERT_VALID(pDoc);

       // create a frame wired to the specified document

 

       ASSERT(m_nIDResource != 0); // must have a resource ID to load from

       CCreateContext context;

       context.m_pCurrentFrame = pOther;

       context.m_pCurrentDoc = pDoc;

       context.m_pNewViewClass = m_pViewClass;

       context.m_pNewDocTemplate = this;

 

       if (m_pFrameClass == NULL)

       {

              TRACE0("Error: you must override CDocTemplate::CreateNewFrame./n");

              ASSERT(FALSE);

              return NULL;

       }

       CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();

       if (pFrame == NULL)

       {

              TRACE1("Warning: Dynamic create of frame %hs failed./n",

                     m_pFrameClass->m_lpszClassName);

              return NULL;

       }

       ASSERT_KINDOF(CFrameWnd, pFrame);

 

       if (context.m_pNewViewClass == NULL)

              TRACE0("Warning: creating frame with no default view./n");

 

       // create new from resource

       if (!pFrame->LoadFrame(m_nIDResource,

                     WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame styles

                     NULL, &context))

       {

              TRACE0("Warning: CDocTemplate couldn't create a frame./n");

              // frame will be deleted in PostNcDestroy cleanup

              return NULL;

       }

 

       // it worked !

       return pFrame;

}

6.     BOOL CDocument::OnNewDocument()

{

       if (IsModified())

              TRACE0("Warning: OnNewDocument replaces an unsaved document./n");

 

       DeleteContents();

       m_strPathName.Empty();      // no path name yet

       SetModifiedFlag(FALSE);     // make clean

 

       return TRUE;

}

7.     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,

                            FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);

              }

              END_TRY

              DELETE_EXCEPTION(e);

              return FALSE;

       }

       END_CATCH_ALL

 

       SetModifiedFlag(FALSE);     // start off with unmodified

 

       return TRUE;

}

8.     BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,  CWnd* pParentWnd, CCreateContext* pContext)

{

       // only do this once

       ASSERT_VALID_IDR(nIDResource);

       ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

 

       m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)

 

       CString strFullString;

       if (strFullString.LoadString(nIDResource))

              AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string

 

       VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

 

       // attempt to create the window

       LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);

       LPCTSTR lpszTitle = m_strTitle;

       if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,

         pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))

       {

              return FALSE;   // will self destruct on failure normally

       }

 

       // save the default menu handle

       ASSERT(m_hWnd != NULL);

       m_hMenuDefault = ::GetMenu(m_hWnd);

 

       // load accelerator resource

       LoadAccelTable(MAKEINTRESOURCE(nIDResource));

 

       if (pContext == NULL)   // send initial update

              SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

 

       return TRUE;

}

9.     void DocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,BOOL bMakeVisible)

{

       // just delagate to implementation in CFrameWnd

       pFrame->InitialUpdateFrame(pDoc, bMakeVisible);

}

 

10.     void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)

{

       // if the frame does not have an active view, set to first pane

       CView* pView = NULL;

       if (GetActiveView() == NULL)

       {

              CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);

              if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))

              {

                     pView = (CView*)pWnd;

                     SetActiveView(pView, FALSE);

              }

       }

 

       if (bMakeVisible)

       {

              // send initial update to all views (and other controls) in the frame

              SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

 

              // give view a chance to save the focus (CFormView needs this)

              if (pView != NULL)

                     pView->OnActivateFrame(WA_INACTIVE, this);

 

              // finally, activate the frame

              // (send the default show command unless the main desktop window)

              int nCmdShow = -1;      // default

              CWinApp* pApp = AfxGetApp();

              if (pApp != NULL && pApp->m_pMainWnd == this)

              {

                     nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain

                     pApp->m_nCmdShow = -1; // set to default after first time

              }

              ActivateFrame(nCmdShow);

              if (pView != NULL)

                     pView->OnActivateView(TRUE, pView, pView);

       }

 

       // update frame counts and frame title (may already have been visible)

       if (pDoc != NULL)

              pDoc->UpdateFrameCounts();

       OnUpdateFrameTitle(TRUE);

}