home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap07 / patron / document.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  12KB  |  549 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Patron Chapter 7
  4.  *
  5.  * Implementation of the CPatronDoc derivation of CDocument that
  6.  * manages pages for us.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "patron.h"
  17. #include <memory.h>
  18. #include <dlgs.h>       //Pring Dlg button IDs
  19.  
  20.  
  21. /*
  22.  * CPatronDoc::CPatronDoc
  23.  * CPatronDoc::~CPatronDoc
  24.  *
  25.  * Constructor Parameters:
  26.  *  hInst           HINSTANCE of the application.
  27.  *  pFR             PCFrame of the frame object.
  28.  *  pAdv            PCDocumentAdviseSink to notify on events.
  29.  */
  30.  
  31. CPatronDoc::CPatronDoc(HINSTANCE hInst, PCFrame pFR
  32.     , PCDocumentAdviseSink pAdv)
  33.     : CDocument(hInst, pFR, pAdv)
  34.     {
  35.     m_pPG=NULL;
  36.     m_lVer=VERSIONCURRENT;
  37.     //CHAPTER7MOD
  38.     m_pIStorage=NULL;
  39.     //End CHAPTER7MOD
  40.     return;
  41.     }
  42.  
  43.  
  44. CPatronDoc::~CPatronDoc(void)
  45.     {
  46.     if (NULL!=m_pPG)
  47.         delete m_pPG;
  48.  
  49.     //CHAPTER7MOD
  50.     ReleaseInterface(m_pIStorage);
  51.     //End CHAPTER7MOD
  52.  
  53.     return;
  54.     }
  55.  
  56.  
  57.  
  58.  
  59.  
  60. /*
  61.  * CPatronDoc::Init
  62.  *
  63.  * Purpose:
  64.  *  Initializes an already created document window.  The client
  65.  *  actually creates the window for us, then passes that here for
  66.  *  further initialization.
  67.  *
  68.  * Parameters:
  69.  *  pDI             PDOCUMENTINIT containing initialization
  70.  *                  parameters.
  71.  *
  72.  * Return Value:
  73.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  74.  */
  75.  
  76. BOOL CPatronDoc::Init(PDOCUMENTINIT pDI)
  77.     {
  78.     //Change the stringtable range to our customization.
  79.     pDI->idsMin=IDS_DOCUMENTMIN;
  80.     pDI->idsMax=IDS_DOCUMENTMAX;
  81.  
  82.     //Do default initialization
  83.     if (!CDocument::Init(pDI))
  84.         return FALSE;
  85.  
  86.     //Pages are created when we get a Load later.
  87.     return TRUE;
  88.     }
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95. /*
  96.  * CPatronDoc::FMessageHook
  97.  *
  98.  * Purpose:
  99.  *  Processes WM_SIZE for the document so we can resize the Pages
  100.  *  window.
  101.  *
  102.  * Parameters:
  103.  *  <WndProc Parameters>
  104.  *  pLRes           LRESULT * in which to store the return
  105.  *                  value for the message.
  106.  *
  107.  * Return Value:
  108.  *  BOOL            TRUE to prevent further processing,
  109.  *                  FALSE otherwise.
  110.  */
  111.  
  112. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  113.     , LPARAM lParam, LRESULT *pLRes)
  114.     {
  115.     UINT        dx, dy;
  116.     RECT        rc;
  117.  
  118.     *pLRes=0;
  119.  
  120.     //Eat to prevent flickering
  121.     if (WM_ERASEBKGND==iMsg)
  122.         return TRUE;
  123.  
  124.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  125.         {
  126.         dx=LOWORD(lParam);
  127.         dy=HIWORD(lParam);
  128.  
  129.         if (SIZE_MINIMIZED!=wParam)
  130.             {
  131.             //Resize Pages window to fit the new document size.
  132.             GetClientRect(hWnd, &rc);
  133.             m_pPG->RectSet(&rc, FALSE);
  134.             }
  135.         }
  136.  
  137.     /*
  138.      * We return FALSE even on WM_SIZE so we can let the default
  139.      * procedure handle maximized MDI child windows appropriately.
  140.      */
  141.     return FALSE;
  142.     }
  143.  
  144.  
  145.  
  146.  
  147.  
  148. /*
  149.  * CPatronDoc::Clear
  150.  *
  151.  * Purpose:
  152.  *  Sets all contents in the document back to defaults with no
  153.  *  filename.
  154.  *
  155.  * Paramters:
  156.  *  None
  157.  *
  158.  * Return Value:
  159.  *  None
  160.  */
  161.  
  162. void CPatronDoc::Clear(void)
  163.     {
  164.     //Completely reset the pages
  165.     //CHAPTER7MOD
  166.     if (NULL!=m_pPG)
  167.         m_pPG->StorageSet(NULL, FALSE, FALSE);
  168.     //End CHAPTER7MOD
  169.  
  170.     CDocument::Clear();
  171.     m_lVer=VERSIONCURRENT;
  172.     return;
  173.     }
  174.  
  175.  
  176.  
  177.  
  178.  
  179. /*
  180.  * CPatronDoc::Load
  181.  *
  182.  * Purpose:
  183.  *  Loads a given document without any user interface overwriting
  184.  *  the previous contents of the editor.
  185.  *
  186.  * Parameters:
  187.  *  fChangeFile     BOOL indicating if we're to update the window
  188.  *                  title and the filename from using this file.
  189.  *  pszFile         LPTSTR to the filename to load.  Could be NULL
  190.  *                  for an untitled document.
  191.  *
  192.  * Return Value:
  193.  *  UINT            An error value from DOCERR_*
  194.  */
  195.  
  196. UINT CPatronDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  197.     {
  198.     RECT        rc;
  199.     //CHAPTER7MOD
  200.     LPSTORAGE   pIStorage;
  201.     HRESULT     hr;
  202.     CLSID       clsID;
  203.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
  204.                     | STGM_SHARE_EXCLUSIVE;
  205.  
  206.     if (NULL==pszFile)
  207.         {
  208.         //Create a new temp file.
  209.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE
  210.             | STGM_DELETEONRELEASE, 0, &pIStorage);
  211.  
  212.         //Mark this our class since we check with ReadClassStg.
  213.         if (SUCCEEDED(hr))
  214.             WriteClassStg(pIStorage, CLSID_PatronPages);
  215.         }
  216.     else
  217.         {
  218.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  219.         }
  220.  
  221.     if (FAILED(hr))
  222.         return DOCERR_COULDNOTOPEN;
  223.  
  224.     //Check if this is our type of file and exit if not.
  225.     hr=ReadClassStg(pIStorage, &clsID);
  226.  
  227.     if (FAILED(hr) || CLSID_PatronPages!=clsID)
  228.         {
  229.         pIStorage->Release();
  230.         return DOCERR_READFAILURE;
  231.         }
  232.  
  233.     //End CHAPTER7MOD
  234.  
  235.     //Attempt to create our contained Pages window.
  236.     m_pPG=new CPages(m_hInst);
  237.     GetClientRect(m_hWnd, &rc);
  238.  
  239.     //CHAPTER7MOD
  240.     if (!m_pPG->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  241.         , ID_PAGES, NULL))
  242.         {
  243.         pIStorage->Release();
  244.         return DOCERR_READFAILURE;
  245.         }
  246.  
  247.     if (!m_pPG->StorageSet(pIStorage, FALSE, (NULL==pszFile)))
  248.         {
  249.         pIStorage->Release();
  250.         return DOCERR_READFAILURE;
  251.         }
  252.  
  253.     m_pIStorage=pIStorage;
  254.     Rename(pszFile);
  255.  
  256.     //Do initial setup if new file, otherwise Pages handles things.
  257.     if (NULL==pszFile)
  258.         {
  259.         //Go initialize the Pages for the default printer.
  260.         if (!PrinterSetup(NULL, TRUE))
  261.             return DOCERR_COULDNOTOPEN;
  262.  
  263.         //Go create an initial page.
  264.         m_pPG->PageInsert(0);
  265.         }
  266.     //End CHAPTER7MOD
  267.  
  268.     FDirtySet(FALSE);
  269.     return DOCERR_NONE;
  270.     }
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277. //CHAPTER7MOD
  278. /*
  279.  * CPatronDoc::Save
  280.  *
  281.  * Purpose:
  282.  *  Writes the file to a known filename, requiring that the user
  283.  *  has previously used FileOpen or FileSaveAs in order to have
  284.  *  a filename.
  285.  *
  286.  * Parameters:
  287.  *  uType           UINT indicating the type of file the user
  288.  *                  requested to save in the File Save As dialog.
  289.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  290.  *                  current name.
  291.  *
  292.  * Return Value:
  293.  *  UINT            An error value from DOCERR_*
  294.  */
  295.  
  296. UINT CPatronDoc::Save(UINT uType, LPTSTR pszFile)
  297.     {
  298.     HRESULT     hr;
  299.     LPSTORAGE   pIStorage;
  300.  
  301.     //Save or Save As with the same file is just a commit.
  302.     if (NULL==pszFile
  303.         || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  304.         {
  305.         WriteFmtUserTypeStg(m_pIStorage, m_cf
  306.             , PSZ(IDS_CLIPBOARDFORMAT));
  307.  
  308.         //Insure pages are up to date.
  309.         m_pPG->StorageUpdate(FALSE);
  310.  
  311.         //Commit everyting
  312.         m_pIStorage->Commit(STGC_DEFAULT);
  313.  
  314.         FDirtySet(FALSE);
  315.         return DOCERR_NONE;
  316.         }
  317.  
  318.     /*
  319.      * When we're given a name, open the storage, creating it new
  320.      * if it does not exist or overwriting the old one.  Then CopyTo
  321.      * from the current to the new, Commit the new, Release the old.
  322.      */
  323.  
  324.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  325.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  326.  
  327.     if (FAILED(hr))
  328.         return DOCERR_COULDNOTOPEN;
  329.  
  330.     WriteClassStg(pIStorage, CLSID_PatronPages);
  331.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  332.  
  333.     //Insure all pages are up-to-date.
  334.     m_pPG->StorageUpdate(TRUE);
  335.  
  336.     //This also copies the CLSID we stuff in here on file creation.
  337.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  338.  
  339.     if (FAILED(hr))
  340.         {
  341.         SCODE       sc;
  342.  
  343.         pIStorage->Release();
  344.         sc=GetScode(hr);
  345.  
  346.         /*
  347.          * If we failed because of low memory, use IRootStorage
  348.          * to switch into the new file.
  349.          */
  350.         if (E_OUTOFMEMORY==sc)
  351.             {
  352.             LPROOTSTORAGE        pIRoot;
  353.  
  354.             //Delete file we already created
  355.             DeleteFile(pszFile);
  356.  
  357.             if (FAILED(m_pIStorage->QueryInterface
  358.                 (IID_IRootStorage, (PPVOID)&pIRoot)))
  359.                 return DOCERR_WRITEFAILURE;
  360.  
  361.            #ifdef WIN32ANSI
  362.             OLECHAR     szTemp[MAX_PATH];
  363.  
  364.             MultiByteToWideChar(CP_ACP, 0, pszFile, -1, szTemp, MAX_PATH);
  365.             hr=pIRoot->SwitchToFile(szTemp);
  366.            #else
  367.             hr=pIRoot->SwitchToFile(pszFile);
  368.            #endif
  369.             pIRoot->Release();
  370.  
  371.             if (FAILED(hr))
  372.                 return DOCERR_WRITEFAILURE;
  373.  
  374.             //If successful, the Commit below finishes the save.
  375.             pIStorage=m_pIStorage;
  376.             m_pIStorage->AddRef();    //Matches Release below
  377.             }
  378.         }
  379.  
  380.     pIStorage->Commit(STGC_DEFAULT);
  381.  
  382.     /*
  383.      * Revert changes on the original storage.  If this was a temp
  384.      * file, it's deleted since we used STGM_DELETEONRELEASE.
  385.      */
  386.     m_pIStorage->Release();
  387.  
  388.     //Make this new storage current
  389.     m_pIStorage=pIStorage;
  390.     m_pPG->StorageSet(pIStorage, TRUE, FALSE);
  391.  
  392.     FDirtySet(FALSE);
  393.     Rename(pszFile);    //Update caption bar.
  394.  
  395.     return DOCERR_NONE;
  396.     }
  397. //End CHAPTER7MOD
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404. /*
  405.  * CPatronDoc::NewPage
  406.  *
  407.  * Purpose:
  408.  *  Creates a new page in the document's pages control after the
  409.  *  current page.
  410.  *
  411.  * Parameters:
  412.  *  None
  413.  *
  414.  * Return Value:
  415.  *  UINT            Index of the new page.
  416.  */
  417.  
  418. UINT CPatronDoc::NewPage(void)
  419.     {
  420.     FDirtySet(TRUE);
  421.     return m_pPG->PageInsert(0);
  422.     }
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430. /*
  431.  * CPatronDoc::DeletePage
  432.  *
  433.  * Purpose:
  434.  *  Deletes the current page from the document.
  435.  *
  436.  * Parameters:
  437.  *  None
  438.  *
  439.  * Return Value:
  440.  *  UINT            Index of the now current page.
  441.  */
  442.  
  443. UINT CPatronDoc::DeletePage(void)
  444.     {
  445.     FDirtySet(TRUE);
  446.     return m_pPG->PageDelete(0);
  447.     }
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455. /*
  456.  * CPatronDoc::NextPage
  457.  *
  458.  * Purpose:
  459.  *  Shows the next page in the pages window.
  460.  *
  461.  * Parameters:
  462.  *  None
  463.  *
  464.  * Return Value:
  465.  *  UINT            Index of the new page.
  466.  */
  467.  
  468. UINT CPatronDoc::NextPage(void)
  469.     {
  470.     UINT        iPage;
  471.  
  472.     iPage=m_pPG->CurPageGet();
  473.     return m_pPG->CurPageSet(++iPage);
  474.     }
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482. /*
  483.  * CPatronDoc::PreviousPage
  484.  *
  485.  * Purpose:
  486.  *  Shows the previous page in the pages window.
  487.  *
  488.  * Parameters:
  489.  *  None
  490.  *
  491.  * Return Value:
  492.  *  UINT            Index of the new page.
  493.  */
  494.  
  495. UINT CPatronDoc::PreviousPage(void)
  496.     {
  497.     UINT        iPage;
  498.  
  499.     //If iPage is zero, then we wrap around to the end.
  500.     iPage=m_pPG->CurPageGet();
  501.     return m_pPG->CurPageSet(--iPage);
  502.     }
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509. /*
  510.  * CPatronDoc::FirstPage
  511.  *
  512.  * Purpose:
  513.  *  Shows the first page page in the pages window.
  514.  *
  515.  * Parameters:
  516.  *  None
  517.  *
  518.  * Return Value:
  519.  *  UINT            Index of the new page.
  520.  */
  521.  
  522. UINT CPatronDoc::FirstPage(void)
  523.     {
  524.     return m_pPG->CurPageSet(0);
  525.     }
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532. /*
  533.  * CPatronDoc::LastPage
  534.  *
  535.  * Purpose:
  536.  *  Shows the last page in the pages window.
  537.  *
  538.  * Parameters:
  539.  *  None
  540.  *
  541.  * Return Value:
  542.  *  UINT            Index of the last page.
  543.  */
  544.  
  545. UINT CPatronDoc::LastPage(void)
  546.     {
  547.     return m_pPG->CurPageSet(NOVALUE);
  548.     }
  549.