Open File& New File之MFC后台代码分析

Open File& New File之MFC后台代码分析

                                    作者:(ECNU)孟庆涛      Email:mqt-2003@163.com      


     
     

1CWinApp::OnFileNew

Creating an Empty Document: The CWinApp::OnFileNew Function

开始运行时,CWinApp::ProcessShellCommand会自动调用OnFileNew函数

       After your application class’s InitInstance function calls the AddDocTemplate member function, it calls OnFileNew (indirectly through CWinApp::ProcessShellCommand), another important CWinApp member function. OnFileNew sorts through the web of interconnected class names and does the following:

  1. Constructs the document object but does not attempt to read data from disk.
  2. Constructs the main frame object (of class CMainFrame); it also creates the main frame window but does not show it. The main frame window includes the IDR_MAINFRAME menu, the toolbar, and the status bar.
  3. Constructs the view object; it also creates the view window but doesn’t show it.
  4. Establishes connections among the document, main frame, and view objects. Do not confuse these object connections with the class connections established by the call to AddDocTemplate.
  5. Calls the virtual CDocument::OnNewDocument member function for the document object, which calls the virtual DeleteContents function.
  6. Calls the virtual CView::OnInitialUpdate member function for the view object.
  7. Calls the virtual CFrameWnd::ActivateFrame for the frame object to show the main frame window together with the menus, view window, and control bars.
2OnFileOpen
      
      

When the MFC Application Wizard generates an application, it maps the File Open menu command to the CWinApp::OnFileOpen member function. When called, this function invokes a sequence of functions to accomplish these steps:

1.     Prompts the user to select a file.

2.     Calls the virtual function CDocument::OnOpenDocument for the already existing document object. This function opens the file, calls CDocument::DeleteContents, and constructs a CArchive object set for loading. It then calls the document’s Serialize function, which loads data from the archive.

3.     Calls the view’s OnInitialUpdate function.

3MFC源代码分析:
注意:表格左边是新建文件过程,右边是打开文件过程,没分左右的则是二者的功用部分。下面都是MFC
后台代码,涉及到序列化问题等。总之,自己品味,其乐无穷。:)

   
   
    
     
   
   

NEW

Open

void CWinApp::OnFileNew()

{

         if (m_pDocManager != NULL)

                   m_pDocManager->OnFileNew();

}

void CWinApp::OnFileOpen()

{

         ASSERT(m_pDocManager != NULL);

         m_pDocManager->OnFileOpen();

}

void CDocManager::OnFileNew()

{

         if (m_templateList.IsEmpty())

         {

         TRACE(traceAppMsg, 0, "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_PTR 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

}

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

}

 

 

CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)

{

         ASSERT(m_pDocManager != NULL);

         return   m_pDocManager->OpenDocumentFile(lpszFileName);

}

 

 

 

 

 

 

 

 

 

 

 

 

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;        

         if( AfxFullPath(szPath, szTemp) == FALSE )

         {

                   ASSERT(FALSE);

                   return NULL; // We won't open the file. MFC requires paths with

                                // length < _MAX_PATH

         }

         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)

                                     TRACE(traceAppMsg, 0, "Error: Can not find a frame for document to activate./n");

                            else

                            {pFrame->ActivateFrame();

                                     if (pFrame->GetParent() != NULL)

                                     {

                                               CFrameWnd* pAppFrame;

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

                                               {

                                                        ASSERT_KINDOF(CFrameWnd, pAppFrame);

                                                        pAppFrame->ActivateFrame();

                                               }

                                     }

                            }

                   }

                   else

                            TRACE(traceAppMsg, 0, "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);

}

 

: 单文档模板

CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMakeVisible)

// if lpszPathName == NULL => create new file of this type

{

CDocument* pDocument = NULL;

CFrameWnd* pFrame = NULL;

BOOL bCreated = FALSE;      // => doc and frame created

BOOL bWasModified = FALSE;

 

if (m_pOnlyDoc != NULL)

{

// already have a document - reinit it

pDocument = m_pOnlyDoc;

if (!pDocument->SaveModified())

return NULL;        // leave the original one

 

pFrame = (CFrameWnd*)AfxGetMainWnd();

ASSERT(pFrame != NULL);

ASSERT_KINDOF(CFrameWnd, pFrame);

ASSERT_VALID(pFrame);

}

else

{

// create a new document

pDocument = CreateNewDocument();    //建立一个新的文档对象

ASSERT(pFrame == NULL);     // will be created below

bCreated = TRUE;

}

if (pDocument == NULL)

{

AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);

return NULL;

}

ASSERT(pDocument == m_pOnlyDoc);

 

if (pFrame == NULL)

{

ASSERT(bCreated);

 

// create frame - set as main document frame

BOOL bAutoDelete = pDocument->m_bAutoDelete;

pDocument->m_bAutoDelete = FALSE;

// don't destroy if something goes wrong

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;

}

}

if (lpszPathName == NULL)       //  File/NEW而言

{

// create a new document

SetDefaultTitle(pDocument);

 

// avoid creating temporary compound file when starting up invisible

if (!bMakeVisible)

pDocument->m_bEmbedded = TRUE;

 

if (!pDocument->OnNewDocument())//调用前面建立的文档对象的函数,建立新文档

{

// user has been alerted to what failed in OnNewDocument

TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE./n");

if (bCreated)

pFrame->DestroyWindow();    // will destroy document

return NULL;

}

}

else                    //File/Open而言

{

CWaitCursor wait;

// open an existing document

bWasModified = pDocument->IsModified();

pDocument->SetModifiedFlag(FALSE);  // not dirty for open

if (!pDocument->OnOpenDocument(lpszPathName))

{

// user has been alerted to what failed in OnOpenDocument

TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE./n");

if (bCreated)

{

pFrame->DestroyWindow();    // will destroy document

}

else if (!pDocument->IsModified())

{

// original document is untouched

   pDocument->SetModifiedFlag(bWasModified);

}

else

{

// we corrupted the original document

SetDefaultTitle(pDocument);

if (!pDocument->OnNewDocument())

{

TRACE(traceAppMsg, 0, "Error: OnNewDocument failed after trying "

"to open a document - trying to continue./n");

// assume we can continue

}

}

return NULL;        // open failed

}

 pDocument->SetPathName(lpszPathName);

}

 

CWinThread* pThread = AfxGetThread();

ASSERT(pThread);

if (bCreated && pThread->m_pMainWnd == NULL)

{

// set as main frame (InitialUpdateFrame will show the window)

pThread->m_pMainWnd = pFrame;

   }

InitialUpdateFrame(pFrame, pDocument, bMakeVisible);

return pDocument;

}

: 多文档模板:

CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,

         BOOL bMakeVisible)

{

         CDocument* pDocument = CreateNewDocument();

         if (pDocument == NULL)

         {

                   TRACE(traceAppMsg, 0, "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

                            TRACE(traceAppMsg, 0, "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

                            TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE./n");

                            pFrame->DestroyWindow();

                            return NULL;

                   }

                   pDocument->SetPathName(lpszPathName);

         }

 

         InitialUpdateFrame(pFrame, pDocument, bMakeVisible);

         return pDocument;

}

 

 

BOOL CDocument::OnNewDocument()

{

#ifdef _DEBUG

         if(IsModified())

                   TRACE(traceAppMsg, 0, "Warning: OnNewDocument replaces an unsaved document./n");

#endif

 

         DeleteContents();

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

         SetModifiedFlag(FALSE);     // make clean

         return TRUE;

}

 

BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)

{

#ifdef _DEBUG

         if (IsModified())

                   TRACE(traceAppMsg, 0, "Warning: OnOpenDocument replaces an unsaved document./n");

#endif

         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;

}

 

 

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)

      {

           TRACE(traceAppMsg, 0, "Error: you must override CDocTemplate::CreateNewFrame./n");

           ASSERT(FALSE);

           return NULL;

      }

      CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();   //动态创建

      if (pFrame == NULL)

      {

           TRACE(traceAppMsg, 0, "Warning: Dynamic create of frame %hs failed./n",m_pFrameClass->m_lpszClassName);

           return NULL;

      }

      ASSERT_KINDOF(CFrameWnd, pFrame);

 

      if (context.m_pNewViewClass == NULL)

           TRACE(traceAppMsg, 0, "Warning: creating frame with no default view./n");

 

      // create new from resource

      if (!pFrame->LoadFrame(m_nIDResource,             WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame stylesNULL, &context)) 

      {

           TRACE(traceAppMsg, 0, "Warning: CDocTemplate couldn't create a frame./n");

           // frame will be deleted in PostNcDestroy cleanup

           return NULL;

      }

 

      // it worked !

      return pFrame;

}

CDocument* CDocTemplate::CreateNewDocument()

{

      // default implementation constructs one from CRuntimeClass

      if (m_pDocClass == NULL)

      {

     TRACE(traceAppMsg, 0, "Error: you must override CDocTemplate::CreateNewDocument./n");

           ASSERT(FALSE);

           return NULL;

      }

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

//动态创建(在运行的时候创建);

      if (pDocument == NULL)

      {

      TRACE(traceAppMsg, 0, "Warning: Dynamic create of document type %hs failed./n",m_pDocClass->m_lpszClassName);

           return NULL;

      }

      ASSERT_KINDOF(CDocument, pDocument);

      AddDocument(pDocument);

      return pDocument;

}

 

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;

 

         // If we've been asked to open a file, call OpenDocumentFile()

 

     case CCommandLineInfo::FileOpen:

         if (!OpenDocumentFile(rCmdInfo.m_strFileName))

              bResult = FALSE;

         break;

 

         // If the user wanted to print, hide our main window and

         // fire a message to ourselves to start the printing

 

     case CCommandLineInfo::FilePrintTo:

     case CCommandLineInfo::FilePrint:

         m_nCmdShow = SW_HIDE;

         ASSERT(m_pCmdInfo == NULL);

         if(OpenDocumentFile(rCmdInfo.m_strFileName))

         {

              m_pCmdInfo = &rCmdInfo;

              m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);

              m_pCmdInfo = NULL;

         }

         bResult = FALSE;

         break;

 

         // If we're doing DDE, hide ourselves

 

     case CCommandLineInfo::FileDDE:

         m_pCmdInfo = (CCommandLineInfo*)(UINT_PTR)m_nCmdShow;

         m_nCmdShow = SW_HIDE;

         break;

 

     // If we've been asked to register, exit without showing UI.

     // Registration was already done in InitInstance().

     case CCommandLineInfo::AppRegister:

         {

              BOOL bRegistered = Register();

              bResult = FALSE;

              if (!rCmdInfo.m_bRunEmbedded)

              {

                   bRegistered;

//                 if (bRegistered)

//                     AfxMessageBox(AFX_IDP_REG_DONE);

//                 else

//                     AfxMessageBox(AFX_IDP_REG_FAILURE);

              }

              bResult = FALSE;    // that's all we do

 

              // If nobody is using it already, we can use it.

              // We'll flag that we're unregistering and not save our state

              // on the way out. This new object gets deleted by the

              // app object destructor.

 

              if (m_pCmdInfo == NULL)

              {

                   m_pCmdInfo = new CCommandLineInfo;

                   m_pCmdInfo->m_nShellCommand = CCommandLineInfo::AppUnregister;

              }

              break;

         }

 

     // If we've been asked to unregister, unregister and then terminate

     case CCommandLineInfo::AppUnregister:

         {

              BOOL bUnregistered = Unregister();

 

              // if you specify /EMBEDDED, we won't make an success/failure box

              // this use of /EMBEDDED is not related to OLE

 

              if (!rCmdInfo.m_bRunEmbedded)

              {

                   if (bUnregistered)

                       AfxMessageBox(AFX_IDP_UNREG_DONE);

                   else

                       AfxMessageBox(AFX_IDP_UNREG_FAILURE);

              }

              bResult = FALSE;    // that's all we do

 

              // If nobody is using it already, we can use it.

              // We'll flag that we're unregistering and not save our state

              // on the way out. This new object gets deleted by the

              // app object destructor.

 

              if (m_pCmdInfo == NULL)

              {

                   m_pCmdInfo = new CCommandLineInfo;

                   m_pCmdInfo->m_nShellCommand = CCommandLineInfo::AppUnregister;

              }

         }

         break;

     }

     return bResult;

}

 

 

4:File/Save &File/Save As

     When the MFC Application Wizard generates an application, it maps the File Save menu command to the OnFileSave member function of the CDocument class. OnFileSave calls the CDocument function OnSaveDocument, which in turn calls your document’s Serialize function with an archive object set for storing. The File Save As menu command is handled in a similar manner: It is mapped to the CDocument function OnFileSaveAs, which calls OnSaveDocument. Here the application framework does all the file management necessary to save a document on disk.

Save

Save As

void CDocument::OnFileSave()

{

         DoFileSave();

}

void CDocument::OnFileSaveAs()

{

         if(!DoSave(NULL))

                   TRACE(traceAppMsg, 0, "Warning: File save-as failed./n");

}

BOOL CDocument::DoFileSave()

{

         DWORD dwAttrib = GetFileAttributes(m_strPathName);

         if (dwAttrib & FILE_ATTRIBUTE_READONLY)

         {

                   // we do not have read-write access or the file does not (now) exist

                   if (!DoSave(NULL))

                   {

         TRACE(traceAppMsg, 0, "Warning: File save with new name failed./n");

                            return FALSE;

                   }

         }

         else

         {

                   if (!DoSave(m_strPathName))

                   {

                            TRACE(traceAppMsg, 0, "Warning: File save failed./n");

                            return FALSE;

                   }

         }

      return TRUE;}

 

 

 

 

 

BOOL CDocument::DoSave(LPCTSTR lpszPathName, BOOL bReplace)

         // Save the document data to a file

         // lpszPathName = path name where to save document file

         // if lpszPathName is NULL then the user will be prompted (SaveAs)

         // note: lpszPathName can be different than 'm_strPathName'

         // if 'bReplace' is TRUE will change file name if successful (SaveAs)

         // if 'bReplace' is FALSE will not change path name (SaveCopyAs)

{

         CString newName = lpszPathName;

         if (newName.IsEmpty())

         {

                   CDocTemplate* pTemplate = GetDocTemplate();

                   ASSERT(pTemplate != NULL);

 

                   newName = m_strPathName;

                   if (bReplace && newName.IsEmpty())

                   {

                            newName = m_strTitle;

                            // check for dubious filename

                            int iBad = newName.FindOneOf(_T(":///"));

                            if (iBad != -1)

                                     newName.ReleaseBuffer(iBad);

 

                            // append the default suffix if there is one

                            CString strExt;

                            if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&

                              !strExt.IsEmpty())

                            {

                                     ASSERT(strExt[0] == '.');

                                     int iStart = 0;

                                     newName += strExt.Tokenize(_T(";"), iStart);

                            }

                   }

                   if (!AfxGetApp()->DoPromptFileName(newName,

                     bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,

                     OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, pTemplate))

                            return FALSE;       // don't even attempt to save

         }

         CWaitCursor wait;

         if (!OnSaveDocument(newName))

         {

                   if (lpszPathName == NULL)

                   {

                            // be sure to delete the file

                            TRY

                            {

                                     CFile::Remove(newName);

                            }

                            CATCH_ALL(e)

                            {

                                     TRACE(traceAppMsg, 0, "Warning: failed to delete file after failed SaveAs./n");

                                     DELETE_EXCEPTION(e);

                            }

                            END_CATCH_ALL

                   }

                   return FALSE;

         }

         // reset the title and change the document name

         if (bReplace)

                   SetPathName(newName);

         return TRUE;        // success

}

BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName)

{

         CFileException fe;

         CFile* pFile = NULL;

         pFile = GetFile(lpszPathName, CFile::modeCreate |

                   CFile::modeReadWrite | CFile::shareExclusive, &fe);

         if (pFile == NULL)

         {

                   ReportSaveLoadException(lpszPathName, &fe,

                            TRUE, AFX_IDP_INVALID_FILENAME);

                   return FALSE;

         }

         CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete);

         saveArchive.m_pDocument = this;

         saveArchive.m_bForceFlat = FALSE;

         TRY

         {

                   CWaitCursor wait;

                   Serialize(saveArchive);     // save me

                   saveArchive.Close();

                   ReleaseFile(pFile, FALSE);

         }

         CATCH_ALL(e)

         {

                   ReleaseFile(pFile, TRUE);

                   TRY

                   {

                            ReportSaveLoadException(lpszPathName, e,

                                     TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);

                   }

                   END_TRY

                   DELETE_EXCEPTION(e);

                   return FALSE;

         }

         END_CATCH_ALL

         SetModifiedFlag(FALSE);     // back to unmodified

         return TRUE;        // success

}

 

 
MFC打开文件和文件夹 一、利用API实现打开文件对话框和利用MFC来实现打开文件对话框。 方法一:API部分: // OPENFILENAME ofn; // TCHAR szFile[MAX_PATH]; // ZeroMemory(&ofn,sizeof(ofn)); // ofn.lStructSize = sizeof(ofn); // ofn.lpstrFile = szFile; // ofn.lpstrFile[0] = TEXT('/0'); // ofn.nMaxFile = sizeof(szFile); // ofn.lpstrFilter = TEXT("all/0*.*/0jpg/0*.jpg/0bmp/0*.bmp/0"); //定义三个选项,all,text和exe // ofn.nFilterIndex = 1; //定义首选项是哪一个 // ofn.lpstrFileTitle = NULL; // ofn.nMaxFileTitle = 0; // ofn.lpstrInitialDir = NULL; // ofn.Flags = OFN_EXPLORER |OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; // if(GetOpenFileName(&ofn)) // { // ::SetDlgItemText(this->m_hWnd,IDC_EDIT1,szFile); // } 方法二、MFC实现 // CFileDialog dlg(TRUE, NULL, NULL, // OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, // NULL); // // if(dlg.DoModal() == IDOK) // { // szFilename = dlg.GetPathName(); // ::MessageBox(NULL,szFilename,NULL,MB_OK); // } 注意:打开文件的方式和打开文件夹的方式是不同的。打开文件的方式是不断的打开直到出现末端为文件,否则遇到文件夹还要继续打开。而打开文件夹则是只要选择到一个路径的文件夹就打开。 下面的这种方式是打开文件夹:MFC实现。 static TCHAR strDirName[MAX_PATH]; BROWSEINFO bi; CString szString = TEXT("选择一个源文件子文件夹"); bi.hwndOwner = ::GetFocus(); bi.pidlRoot = NULL; bi.pszDisplayName = strDirName; bi.lpszTitle = szString; bi.ulFlags = BIF_BROWSEFORCOMPUTER | BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; bi.lParam = 0; bi.iImage = 0; LPITEMIDLIST pItemIDList = ::SHBrowseForFolder(&bi); if(pItemIDList == NULL) { return ; } ::SHGetPathFromIDList(pItemIDList, strDirName); CString str = strDirName; if(str != "" && str.Right(1) != '//') str += '//'; ::SetDlgItemText(this->m_hWnd,IDC_EDIT1,str);
CFile //创建/打开文件 CFile file; file.Open(_T("test.txt"),CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite); 文件打开模式可组合使用,用“|”隔开,常用的有以下几种: CFile::modeCreate:以新建方式打开,如果文件不存在,新建;如果文件已存在,把该文件长度置零,即清除文件原有内容。 CFile::modeNoTruncate:以追加方式打开,如果文件存在,打开并且不将文件长度置零,如果文件不存在,会抛出异常。一般与CFile::modeCreate一起使用,则文件不存在时,新建一个文件;存在就进行追加操作。 CFile::modeReadWrite:以读写方式打开文件。 CFile::modeRead:只读。 CFile::modeWrite:只写。 //写入数据 CString strValue = "Hello World!"; file.Write(strValue,strValue.GetLength()); //追加数据 file.SeekToEnd(); //将指针移至文件末尾进行追加 file.Write(strValue,strValue.GetLength()); //关闭文件 file.Close(); CStdioFile CStdioFile是CFile的派生类,对文件进行流式操作,对于文本文件的读写很有用处,可按行读取写入。 //写入数据 CString strValue = "Hello World!"; file.WriteString(strValue); //读取数据 CString strRead; file.ReadString(strRead); 当文件存在多行数据需要逐行读取时,可用函数BOOL CStdioFile::ReadString(CString& rString),当遇到"\n "时读取截断,如果文件未读完,返回true,否则返回false。 //逐行读取文件内容,存入strRead while(file.ReadString(strRead)) { ...; } 各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的。本文将对Visual C++中有关文件操作进行全面的介绍,并对在文件操作中经常遇到的一些疑难问题进行详细的分析。   1.文件的查找   当对一个文件操作时,如果不知道该文件是否存在,就要首先进行查找。MFC中有一个专门用来进行文件查找的类CFileFind,使用它可以方便快捷地进行文件的查找。下面这段代码演示了这个类的最基本使用方法。   CString strFileTitle;   CFileFind finder;   BOOL bWorking = finder.FindFile("C:\\windows\\sysbkup\\*.cab");   while(bWorking)   {   bWorking=finder.FindNextFile();   strFileTitle=finder.GetFileTitle();   }   2.文件的打开/保存对话框   让用户选择文件进行打开和存储操作时,就要用到文件打开/保存对话框。MFC的类CFileDialog用于实现这种功能。使用CFileDialog声明一个对象时,第一个BOOL型参数用于指定文件的打开或保存,当为TRUE时将构造一个文件打开对话框,为FALSE时构造一个文件保存对话框。   在构造CFileDialog对象时,如果在参数中指定了OFN_ALLOWMULTISELECT风格,则在此对话框中可以进行多选操作。此时要重点注意为此CFileDialog对象的m_ofn.lpstrFile分配一块内存,用于存储多选操作所返回的所有文件路径名,如果不进行分配或分配的内存过小就会导致操作失败。下面这段程序演示了文件打开对话框的使用方法。   CFileDialog mFileDlg(TRUE,NULL,NULL,   OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,   "All Files (*.*)|*.*||",AfxGetMainWnd());   CString str(" ",10000);   mFileDlg.m_ofn.lpstrFile=str.GetBuffer(10000);   str.ReleaseBuffer();   POSITION mPos=mFileDlg.GetStartPosition();   CString pathName(" ",128);   CFileStatus status;   while(mPos!=NULL)   {   pathName=mFileDlg.GetNextPathName(mPos);   CFile::GetStatus( pathName, status );   }   3.文件的读写   文件的读写非常重要,下面将重点进行介绍。文件读写的最普通的方法是直接使用CFile进行,如文件的读写可以使用下面的方法:   //对文件进行读操作   char sRead[2];   CFile mFile(_T("user.txt"),CFile::modeRead);   if(mFile.GetLength()<2)   return;   mFile.Read(sRead,2);   mFile.Close();   //对文件进行写操作   CFile mFile(_T("user.txt "), CFile::modeWrite|CFile::modeCreate);   mFile.Write(sRead,2);   mFile.Flush();   mFile.Close();   虽然这种方法最为基本,但是它的使用繁琐,而且功能非常简单。我向你推荐的是使用CArchive,它的使用方法简单且功能十分强大。首先还是用CFile声明一个对象,然后用这个对象的指针做参数声明一个CArchive对象,你就可以非常方便地存储各种复杂的数据类型了。它的使用方法见下例。   //对文件进行写操作   CString strTemp;   CFile mFile;   mFile.Open("d:\\dd\\try.TRY",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);   CArchive ar(&mFile,CArchive::store);   ar<>strTemp;   ar.Close();   mFile.Close();   CArchive的 <> 操作符用于简单数据类型的读写,对于CObject派生类的对象的存取要使用ReadObject()和WriteObject()。使用CArchive的ReadClass()和WriteClass()还可以进行类的读写,如:   //存储CAboutDlg类   ar.WriteClass(RUNTIME_CLASS(CAboutDlg));   //读取CAboutDlg类   CRuntimeClass* mRunClass=ar.ReadClass();   //使用CAboutDlg类   CObject* pObject=mRunClass->CreateObject();   ((CDialog* )pObject)->DoModal();   虽然VC提供的文档/视结构中的文档也可进行这些操作,但是不容易理解、使用和管理,因此虽然很多VC入门的书上花费大量篇幅讲述文档/视结构,但我建议你最好不要使用它的文档。关于如何进行文档/视的分离有很多书介绍,包括非常著名的《Visual C++ 技术内幕》。   如果你要进行的文件操作只是简单的读写整行的字符串,我建议你使用CStdioFile,用它来进行此类操作非常方便,如下例。   CStdioFile mFile;   CFileException mExcept;   mFile.Open( "d:\\temp\\aa.bat", CFile::modeWrite, &mExcept);   CString string="I am a string.";   mFile.WriteString(string);   mFile.Close();  4.临时文件的使用   正规软件经常用到临时文件,你经常可以会看到C:\Windows\Temp目录下有大量的扩展名为tmp的文件,这些就是程序运行是建立的临时文件。临时文件的使用方法基本与常规文件一样,只是文件名应该调用函数GetTempFileName()获得。它的第一个参数是建立此临时文件的路径,第二个参数是建立临时文件名的前缀,第四个参数用于得到建立的临时文件名。得到此临时文件名以后,你就可以用它来建立并操作文件了,如:   char szTempPath[_MAX_PATH],szTempfile[_MAX_PATH];   GetTempPath(_MAX_PATH, szTempPath);   GetTempFileName(szTempPath,_T ("my_"),0,szTempfile);   CFile m_tempFile(szTempfile,CFile:: modeCreate|CFile:: modeWrite);   char m_char='a';   m_tempFile.Write(&m_char,2);   m_tempFile.Close();   5.文件的复制、删除等   MFC中没有提供直接进行这些操作的功能,因而要使用SDK。SDK中的文件相关函数常用的有CopyFile()、CreateDirectory()、DeleteFile()、MoveFile()。它们的用法很简单,可参考MSDN。 1,判断文件是否存在 access(filename,mode); 2,对于不同用途又不同的文件操作,其中API函数CreateFile()也是比较有用处理方式,对于巨型文件很合适的其他的楼上的大都说了,不重复了. [1]显示对话框,取得文件名 CString FilePathName; CFileDialog dlg(TRUE);///TRUE为OPEN对话框,FALSE为S***E AS对话框 if (dlg.DoModal() == IDOK) FilePathName=dlg.GetPathName(); 相关信息:CFileDialog 用于取文件名的几个成员函数: 假如选择的文件是C:\WINDOWS\TEST.EXE 则(1)GetPathName();取文件名全称,包括完整路径。取回C:\WINDOWS\TEST.EXE (2)GetFileTitle();取文件全名:TEST.EXE (3)GetFileName();取回TEST (4)GetFileExt();取扩展名EXE [2]打开文件 CFile file("C:\HELLO.TXT",CFile::modeRead);//只读方式打开 //CFile::modeRead可改为 CFile::modeWrite(只写), //CFile::modeReadWrite(读写),CFile::modeCreate(新建) 例子: { CFile file; file.Open("C:\HELLO.TXT",CFile::modeCreate|Cfile::modeWrite); . . . } [3]移动文件指针 file.Seek(100,CFile::begin);///从文件头开始往下移动100字节 file.Seek(-50,CFile::end);///从文件末尾往上移动50字节 file.Seek(-30,CFile::current);///从当前位置往上移动30字节 file.SeekToBegin();///移到文件头 file.SeekToEnd();///移到文件尾 [4]读写文件 读文件: char buffer[1000]; file.Read(buffer,1000); 写文件: CString string("自强不息"); file.Write(string,8); [5]关闭文件 file.Close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值