home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK8 / MFC / SAMPLES / OCLIENT / FILEIO.CP$ / fileio
Encoding:
Text File  |  1992-03-14  |  7.5 KB  |  348 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and Microsoft
  7. // QuickHelp documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "oclient.h"
  12. #include "mainwnd.h"
  13. #include "itemwnd.h"
  14.  
  15. #include <afxdlgs.h>
  16.  
  17. /////////////////////////////////////////////////////////////////////////////
  18. // File menu commands
  19.  
  20. void CMainWnd::OnFileNew()
  21. {
  22.     if (!SaveAsNeeded())
  23.         return;
  24.  
  25.     InitFile(FALSE);
  26. }
  27.  
  28. void CMainWnd::OnFileOpen()
  29. {
  30.     if (!SaveAsNeeded())
  31.         return;
  32.  
  33.     CString newName = m_fileName;
  34.     if (!DoFileDlg(newName, IDS_OPENFILE, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST))
  35.         return;
  36.  
  37.     CFile file;
  38.     if (!file.Open(newName, CFile::modeRead | CFile::shareDenyWrite))
  39.     {
  40.         ErrorMessage(E_FAILED_TO_READ_FILE);
  41.         return;
  42.     }
  43.  
  44.     /* Deregister the current document, and re-init */
  45.     m_fileName = newName;
  46.     InitFile(TRUE);
  47.  
  48.     /* If we failed to read, we already destroyed
  49.      * all the objects, so go back to File New-like state */
  50.     Hourglass(TRUE);
  51.     TRY
  52.     {
  53.         CArchive loadArchive(&file, CArchive::load);
  54.         this->Serialize(loadArchive);       // load me
  55.     }
  56.     CATCH (CException, e)
  57.     {
  58.         Hourglass(FALSE);
  59.         ErrorMessage(E_FAILED_TO_READ_FILE);
  60.         InitFile(FALSE);    // just re-init it like New
  61.         file.Close();
  62.         return;
  63.     }
  64.     END_CATCH
  65.  
  66.     Hourglass(FALSE);
  67.     m_fDirty = FALSE;
  68.     file.Close();
  69. }
  70.  
  71.  
  72. void CMainWnd::OnFileSave()
  73. {
  74.     // do the save
  75.     DoSave(m_fileName);
  76. }
  77.  
  78.  
  79. void CMainWnd::OnFileSaveAs()
  80. {
  81.     // save to new name
  82.     DoSave(NULL);
  83. }
  84.  
  85. /////////////////////////////////////////////////////////////////////////////
  86. // Basic file operations
  87.  
  88. void CMainWnd::InitFile(BOOL fOpen)
  89. {
  90.     m_fDirty = FALSE;
  91.  
  92.     /* If New, reset the file name */
  93.     if (!fOpen)
  94.         m_fileName.Empty();
  95.  
  96.     /* Deregister the edited document, and wipe out the objects. */
  97.     DeregisterDoc();
  98.  
  99.     /* Reset the title bar, and register the OLE client document */
  100.     SetTitle();
  101. }
  102.  
  103. static void FormatString1(CString&s, UINT idFormat,
  104.     const char* szData, const char* szAlternate)
  105. {
  106.     char szTmp[CBMESSAGEMAX];
  107.     CString format;
  108.     format.LoadString(idFormat);
  109.  
  110.     if (szData[0] == '\0')
  111.         szData = szAlternate;
  112.  
  113.     wsprintf(szTmp, (LPCSTR)format, (LPCSTR)szData);
  114.     s = szTmp;
  115. }
  116.  
  117. BOOL CMainWnd::SaveAsNeeded()
  118. {
  119.     if (!m_fDirty)
  120.         return TRUE;
  121.  
  122.     CString prompt;
  123.     FormatString1(prompt, IDS_MAYBESAVE, m_fileName, strUntitled);
  124.  
  125.     /* Ask "Do you wish to save your changes?" */
  126.     switch (MessageBox(prompt, AfxGetAppName(), MB_YESNOCANCEL | MB_ICONQUESTION))
  127.     {
  128.     case IDCANCEL:
  129.         return FALSE;       // don't continue
  130.         break;
  131.  
  132.     case IDYES:
  133.         /* If so, either Save or Update, as appropriate. */
  134.         if (!DoSave(m_fileName))
  135.             return FALSE;       // don't continue
  136.         break;
  137.  
  138.     case IDNO:
  139.         /* If not saving changes, revert the document */
  140.         m_document.NotifyRevert();
  141.         break;
  142.  
  143.     default:
  144.         ASSERT(FALSE);
  145.         break;
  146.     }
  147.     return TRUE;    // keep going
  148. }
  149.  
  150. BOOL CMainWnd::DoSave(const char* szFileName)
  151.         // note: can be different than 'm_fileName' for SaveAs
  152.         // will set 'm_fileName' if successful
  153. {
  154.     CString newName = szFileName;
  155.     if (newName.IsEmpty())
  156.     {
  157.         // no file name, prompt for new one
  158.         if (!DoFileDlg(newName, IDS_SAVEFILE,
  159.           OFN_HIDEREADONLY | OFN_PATHMUSTEXIST))
  160.             return FALSE;
  161.     }
  162.  
  163.     CFile file;
  164.     if (!file.Open(newName, CFile::modeCreate |
  165.       CFile::modeReadWrite | CFile::shareExclusive))
  166.     {
  167.         ErrorMessage(E_INVALID_FILENAME);
  168.         return FALSE;
  169.     }
  170.  
  171.     Hourglass(TRUE);
  172.     TRY
  173.     {
  174.         CArchive saveArchive(&file, CArchive::store);
  175.         this->Serialize(saveArchive);       // save me
  176.     }
  177.     CATCH (CException, e)
  178.     {
  179.         Hourglass(FALSE);
  180.         ErrorMessage(E_FAILED_TO_SAVE_FILE);
  181.         file.Close();
  182.         return FALSE;
  183.     }
  184.     END_CATCH
  185.  
  186.     Hourglass(FALSE);
  187.     file.Close();
  188.  
  189.     // notify library
  190.     m_document.NotifySaved();
  191.     m_fDirty = FALSE;
  192.  
  193.     // Reset the title and change the document name
  194.     m_fileName = newName;
  195.     SetTitle();
  196.  
  197.     return TRUE;        // success
  198. }
  199.  
  200. /////////////////////////////////////////////////////////////////////////////
  201. // Actual reading/writing of data
  202.  
  203. void CMainWnd::Serialize(CArchive& ar)
  204. {
  205.     CFrameWnd::Serialize(ar);   // does nothing I hope
  206.     WORD wMagic = 0x0DAF;
  207.  
  208.     if (ar.IsStoring())
  209.     {
  210.         ar << wMagic;
  211.         // First count up number of OLE Objects to write
  212.         CItemWnd* pItemWnd;
  213.         WORD    cCompleteObjectsToWrite = 0;
  214.         WORD    cIncompleteObjects = 0;
  215.  
  216.         for (pItemWnd = (CItemWnd*)GetTopWindow(); pItemWnd != NULL;
  217.             pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow())
  218.         {
  219.             if (pItemWnd->IsComplete())
  220.                 cCompleteObjectsToWrite++;
  221.             else
  222.                 cIncompleteObjects++;
  223.         }
  224.  
  225.         TRACE("%d complete objects to write, %d incomplete ones to ignore\n",
  226.             cCompleteObjectsToWrite, cIncompleteObjects);
  227.  
  228.         CString prompt;
  229.         prompt.LoadString(IDS_SAVEINCOMPLETE);
  230.         if (cIncompleteObjects > 0 && MessageBox(prompt, AfxGetAppName(),
  231.             MB_YESNO | MB_ICONQUESTION) != IDYES)
  232.         {
  233.             TRACE("Aborting save\n");
  234.             AfxThrowArchiveException(CArchiveException::generic);
  235.         }
  236.  
  237.         ar << cCompleteObjectsToWrite;
  238.  
  239. #ifdef _DEBUG
  240.         WORD    cObjectsWritten = 0;
  241. #endif
  242.         // reverse order (easier to rebuild that way)
  243.         for (pItemWnd = (CItemWnd*)GetTopWindow(); pItemWnd != NULL;
  244.             pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow())
  245.         {
  246.             if (pItemWnd->IsComplete())
  247.             {
  248.                 pItemWnd->Serialize(ar);
  249.                 // NOTE: don't use WriteObject since we know the actual
  250.                 //  class for pItemWnd
  251. #ifdef _DEBUG
  252.                 cObjectsWritten++;
  253. #endif
  254.             }
  255.         }
  256. #ifdef _DEBUG
  257.         ASSERT(cObjectsWritten == cCompleteObjectsToWrite);
  258. #endif
  259.     }
  260.     else // loading
  261.     {
  262.         WORD w;
  263.         ar >> w;
  264.  
  265.         if (w != wMagic)
  266.         {
  267.             TRACE("invalid magic number at start of file\n");
  268.             AfxThrowArchiveException(CArchiveException::generic);
  269.         }
  270.  
  271.         WORD cObjectsToRead;
  272.         ar >> cObjectsToRead;
  273.  
  274.         for (UINT iObj = 0; iObj < cObjectsToRead; iObj++)
  275.         {
  276.             CItemWnd* pItemWnd = new CItemWnd(this);
  277.  
  278.             pItemWnd->Serialize(ar);
  279.         }
  280.     }
  281. }
  282.  
  283.  
  284. /////////////////////////////////////////////////////////////////////////////
  285.  
  286. void CMainWnd::SetTitle()
  287. {
  288.     const char* pszName;
  289.     char szTitle[CBMESSAGEMAX + _MAX_PATH];
  290.  
  291.     pszName = (m_fileName.IsEmpty()) ? strUntitled : m_fileName;
  292.     wsprintf(szTitle, "%s - %s", (LPCSTR)AfxGetAppName(), (LPCSTR)pszName);
  293.  
  294.     /* Perform the client document registration */
  295.     if (m_document.IsOpen())
  296.     {
  297.         m_document.NotifyRename(pszName);
  298.     }
  299.     else
  300.     {
  301.         if (!m_document.Register(AfxGetAppName(), pszName))
  302.         {
  303.             ErrorMessage(W_FAILED_TO_NOTIFY);
  304.             ASSERT(!m_document.IsOpen());
  305.         }
  306.     }
  307.  
  308.     SetWindowText(szTitle);
  309. }
  310.  
  311. void CMainWnd::DeregisterDoc()
  312. {
  313.     /* Destroy all the objects */
  314.     ClearAll();
  315.  
  316.     /* Release the document */
  317.     if (m_document.IsOpen())
  318.     {
  319.         m_document.Revoke();
  320.     }
  321. }
  322.  
  323. /////////////////////////////////////////////////////////////////////////////
  324. // File Dialog prompts
  325.  
  326. static void Normalize(LPSTR lpstrFile);
  327.  
  328. BOOL CMainWnd::DoFileDlg(CString& fileName, UINT nIDTitle, DWORD lFlags)
  329. {
  330.     CString title;
  331.     CString filter;
  332.     CString ext;
  333.     VERIFY(title.LoadString(nIDTitle));
  334.     VERIFY(filter.LoadString(IDS_FILTER));
  335.     VERIFY(ext.LoadString(IDS_EXTENSION));
  336.     
  337.  
  338.     CFileDialog dlg(TRUE, ext, fileName, lFlags, filter);
  339.     
  340.     dlg.m_ofn.lpstrTitle = title;
  341.  
  342.     if (dlg.DoModal() == IDCANCEL)
  343.         return FALSE;
  344.  
  345.     fileName = dlg.GetFileName() + '.' + dlg.GetFileExt();
  346.     return TRUE;
  347. }
  348.