MFC OnFileNew OnFileOpen过程分析代码

    技术2026-04-24  6

    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);

    }

    B) OnFileOpen()执行过程分析

    11.             void CWinApp::OnFileOpen()

    {

           ASSERT(m_pDocManager != NULL);

           m_pDocManager->OnFileOpen();

    }

     

    12.             void CDocManager::OnFileOpen()

    {

           // prompt the user (with all document templates)

           CString newName;

           if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,

             OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))

                  return; // open cancelled

     

           AfxGetApp()->OpenDocumentFile(newName);

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

    }

     

    13.             CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)

    {

           ASSERT(m_pDocManager != NULL);

           return m_pDocManager->OpenDocumentFile(lpszFileName);

    }

     

    14.             CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)

    {

           // find the highest confidence

           POSITION pos = m_templateList.GetHeadPosition();

           CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;

           CDocTemplate* pBestTemplate = NULL;

           CDocument* pOpenDocument = NULL;

     

           TCHAR szPath[_MAX_PATH];

           ASSERT(lstrlen(lpszFileName) < _countof(szPath));

           TCHAR szTemp[_MAX_PATH];

           if (lpszFileName[0] == '/"')

                  ++lpszFileName;

           lstrcpyn(szTemp, lpszFileName, _MAX_PATH);

           LPTSTR lpszLast = _tcsrchr(szTemp, '/"');

           if (lpszLast != NULL)

                  *lpszLast = 0;

           AfxFullPath(szPath, szTemp);

           TCHAR szLinkName[_MAX_PATH];

           if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))

                  lstrcpy(szPath, szLinkName);

     

           while (pos != NULL)

           {

                  CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);

                  ASSERT_KINDOF(CDocTemplate, pTemplate);

     

                  CDocTemplate::Confidence match;

                  ASSERT(pOpenDocument == NULL);

                  match = pTemplate->MatchDocType(szPath, pOpenDocument);

                  if (match > bestMatch)

                  {

                         bestMatch = match;

                         pBestTemplate = pTemplate;

                  }

                  if (match == CDocTemplate::yesAlreadyOpen)

                         break;      // stop here

           }

     

           if (pOpenDocument != NULL)

           {

                  POSITION pos = pOpenDocument->GetFirstViewPosition();

                  if (pos != NULL)

                  {

                         CView* pView = pOpenDocument->GetNextView(pos); // get first one

                         ASSERT_VALID(pView);

                         CFrameWnd* pFrame = pView->GetParentFrame();

                         if (pFrame != NULL)

                                pFrame->ActivateFrame();

                         else

                                TRACE0("Error: Can not find a frame for document to activate./n");

                         CFrameWnd* pAppFrame;

                         if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))

                         {

                                ASSERT_KINDOF(CFrameWnd, pAppFrame);

                                pAppFrame->ActivateFrame();

                         }

                  }

                  else

                  {

                         TRACE0("Error: Can not find a view for document to activate./n");

                  }

                  return pOpenDocument;

           }

     

           if (pBestTemplate == NULL)

           {

                  AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);

                  return NULL;

           }

     

           return pBestTemplate->OpenDocumentFile(szPath);

    }

     

    15.             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;

    }

     

    16.             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;

    }

     

    17.             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;

    }

     

    18.             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;

    }

     

    19.             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;

    }

     

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

    {

           // just delagate to implementation in CFrameWnd

           pFrame->InitialUpdateFrame(pDoc, bMakeVisible);

    }

     

    21.     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);

    }

    最新回复(0)