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 / chap21 / patron / document.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-23  |  36.6 KB  |  1,604 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Patron Chapter 21
  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.     m_pIStorage=NULL;
  38.     m_fPrintSetup=TRUE;
  39.     m_pDropTarget=NULL;
  40.  
  41.     //These CFSTR_* values are standard (defined in INC\CLASSLIB.H)
  42.     m_cfEmbeddedObject=RegisterClipboardFormat
  43.         (CFSTR_EMBEDDEDOBJECT);
  44.     m_cfObjectDescriptor=RegisterClipboardFormat
  45.         (CFSTR_OBJECTDESCRIPTOR);
  46.  
  47.     //CHAPTER20MOD
  48.     m_cfLinkSource=RegisterClipboardFormat(CFSTR_LINKSOURCE);
  49.     m_cfLinkSrcDescriptor=RegisterClipboardFormat
  50.         (CFSTR_LINKSRCDESCRIPTOR);
  51.  
  52.     m_fShowTypes=FALSE;
  53.  
  54.     //CHAPTER21MOD
  55.     m_cRef=1L;
  56.     m_fRename=TRUE;
  57.     m_dwRegROT=0L;
  58.     m_dwRegROTWild=0L;
  59.     m_pImpIPersistFile=NULL;
  60.     m_pImpIOleItemContainer=NULL;
  61.     //End CHAPTER21MOD
  62.  
  63.     return;
  64.     }
  65.  
  66.  
  67. CPatronDoc::~CPatronDoc(void)
  68.     {
  69.     //CHAPTER21MOD
  70.     INOLE_RevokeAsRunning(&m_dwRegROT);
  71.     INOLE_RevokeAsRunning(&m_dwRegROTWild);
  72.  
  73.     DeleteInterfaceImp(m_pImpIPersistFile);
  74.     DeleteInterfaceImp(m_pImpIOleItemContainer);
  75.     //End CHAPTER21MOD
  76.  
  77.     if (NULL!=m_pPG)
  78.         delete m_pPG;
  79.  
  80.     ReleaseInterface(m_pIStorage);
  81.     CoFreeUnusedLibraries();
  82.     return;
  83.     }
  84.  
  85.  
  86.  
  87.  
  88. //CHAPTER21MOD
  89.  
  90. /*
  91.  * CPatronDoc::QueryInterface
  92.  * CPatronDoc::AddRef
  93.  * CPatronDoc::Release
  94.  */
  95.  
  96. STDMETHODIMP CPatronDoc::QueryInterface(REFIID riid, PPVOID ppv)
  97.     {
  98.     *ppv=NULL;
  99.  
  100.     /*
  101.      * WARNING:  Because the *ppv=this implicitly does
  102.      * *ppv=(LPVOID)this, the this pointer is incorrectly cast
  103.      * from a CPatronDoc pointer to LPVOID where we want an
  104.      * IUnknown pointer instead.  CPatronDoc uses multiple
  105.      * inheritance here which means that we have to explicitly
  106.      * provide the typecast to select the base class like
  107.      * IUnknown.  If you don't do this, calls to AddRef, for
  108.      * example, might call your desctructor!
  109.      */
  110.  
  111.     if (IID_IUnknown==riid)
  112.         *ppv=(LPUNKNOWN)this;
  113.  
  114.     if (IID_IOleItemContainer==riid || IID_IOleContainer==riid
  115.         || IID_IParseDisplayName==riid)
  116.         *ppv=m_pImpIOleItemContainer;
  117.  
  118.     if (IID_IPersistFile==riid || IID_IPersist==riid)
  119.         *ppv=m_pImpIPersistFile;
  120.  
  121.     if (NULL!=*ppv)
  122.         {
  123.         ((LPUNKNOWN)*ppv)->AddRef();
  124.         return NOERROR;
  125.         }
  126.  
  127.     return ResultFromScode(E_NOINTERFACE);
  128.     }
  129.  
  130.  
  131. STDMETHODIMP_(ULONG) CPatronDoc::AddRef(void)
  132.     {
  133.     return ++m_cRef;
  134.     }
  135.  
  136. STDMETHODIMP_(ULONG) CPatronDoc::Release(void)
  137.     {
  138.     if (0!=--m_cRef)
  139.         return m_cRef;
  140.  
  141.     PostMessage(m_hWnd, WM_CLOSE, 0, 0);
  142.     return 0;
  143.     }
  144. //End CHAPTER21MOD
  145.  
  146.  
  147.  
  148.  
  149. /*
  150.  * CPatronDoc::Init
  151.  *
  152.  * Purpose:
  153.  *  Initializes an already created document window.  The client
  154.  *  actually creates the window for us, then passes that here for
  155.  *  further initialization.
  156.  *
  157.  * Parameters:
  158.  *  pDI             PDOCUMENTINIT containing initialization
  159.  *                  parameters.
  160.  *
  161.  * Return Value:
  162.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  163.  */
  164.  
  165. BOOL CPatronDoc::Init(PDOCUMENTINIT pDI)
  166.     {
  167.     //Change the stringtable range to our customization.
  168.     pDI->idsMin=IDS_DOCUMENTMIN;
  169.     pDI->idsMax=IDS_DOCUMENTMAX;
  170.  
  171.     //Do default initialization
  172.     if (!CDocument::Init(pDI))
  173.         return FALSE;
  174.  
  175.     //Pages are created when we get a Load later.
  176.  
  177.     //CHAPTER21MOD
  178.     //Instantiate our interfaces
  179.     m_pImpIPersistFile=new CImpIPersistFile(this, this);
  180.  
  181.     if (NULL==m_pImpIPersistFile)
  182.         return FALSE;
  183.  
  184.     m_pImpIOleItemContainer=new CImpIOleItemContainer(this, this
  185.         , TRUE);
  186.  
  187.     if (NULL==m_pImpIOleItemContainer)
  188.         return FALSE;
  189.  
  190.     //End CHAPTER21MOD
  191.  
  192.     return TRUE;
  193.     }
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201. /*
  202.  * CPatronDoc::FMessageHook
  203.  *
  204.  * Purpose:
  205.  *  Processes WM_SIZE for the document so we can resize the Pages
  206.  *  window.
  207.  *
  208.  * Parameters:
  209.  *  <WndProc Parameters>
  210.  *  pLRes           LRESULT * in which to store the return
  211.  *                  value for the message.
  212.  *
  213.  * Return Value:
  214.  *  BOOL            TRUE to prevent further processing,
  215.  *                  FALSE otherwise.
  216.  */
  217.  
  218. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  219.     , LPARAM lParam, LRESULT *pLRes)
  220.     {
  221.     UINT        dx, dy;
  222.     RECT        rc;
  223.  
  224.     *pLRes=0;
  225.  
  226.     //Eat to prevent flickering
  227.     if (WM_ERASEBKGND==iMsg)
  228.         return TRUE;
  229.  
  230.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  231.         {
  232.         dx=LOWORD(lParam);
  233.         dy=HIWORD(lParam);
  234.  
  235.         if (SIZE_MINIMIZED!=wParam)
  236.             {
  237.             //Resize Pages window to fit the new document size.
  238.             GetClientRect(hWnd, &rc);
  239.             m_pPG->RectSet(&rc, FALSE);
  240.             }
  241.         }
  242.  
  243.     if (WM_DESTROY==iMsg)
  244.         {
  245.         /*
  246.          * We have to revoke the drop target here because the window
  247.          * will be destroyed and the property forcefully removed
  248.          * before we could do this in the destructor.
  249.          */
  250.         if (NULL!=m_pDropTarget)
  251.             {
  252.             RevokeDragDrop(m_hWnd);
  253.             CoLockObjectExternal(m_pDropTarget, FALSE, TRUE);
  254.             m_pDropTarget->Release();
  255.             }
  256.  
  257.         return FALSE;
  258.         }
  259.  
  260.     /*
  261.      * We return FALSE even on WM_SIZE so we can let the default
  262.      * procedure handle maximized MDI child windows appropriately.
  263.      */
  264.     return FALSE;
  265.     }
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273. /*
  274.  * CPatronDoc::Clear
  275.  *
  276.  * Purpose:
  277.  *  Sets all contents in the document back to defaults with no
  278.  *  filename.
  279.  *
  280.  * Paramters:
  281.  *  None
  282.  *
  283.  * Return Value:
  284.  *  None
  285.  */
  286.  
  287. void CPatronDoc::Clear(void)
  288.     {
  289.     //Completely reset the pages
  290.     if (NULL!=m_pPG)
  291.         m_pPG->StorageSet(NULL, FALSE, FALSE);
  292.  
  293.     CDocument::Clear();
  294.     m_lVer=VERSIONCURRENT;
  295.     return;
  296.     }
  297.  
  298.  
  299.  
  300. //CHAPTER21MOD
  301. /*
  302.  * CPatronDoc::FDirtySet
  303.  *
  304.  * Purpose:
  305.  *  Sets or clears the document 'dirty' flag returning the previous
  306.  *  state of that same flag.  We override this to note change
  307.  *  times in the running object table.
  308.  *
  309.  * Parameters:
  310.  *  fDirty          BOOL indicating the new contents of the dirty
  311.  *                  flag.
  312.  *
  313.  * Return Value:
  314.  *  BOOL            Previous value of the dirty flag.
  315.  */
  316.  
  317. BOOL CPatronDoc::FDirtySet(BOOL fDirty)
  318.     {
  319.     BOOL        fRet;
  320.  
  321.     fRet=CDocument::FDirtySet(fDirty);
  322.     INOLE_NoteChangeTime(m_dwRegROT, NULL, NULL);
  323.     INOLE_NoteChangeTime(m_dwRegROTWild, NULL, NULL);
  324.  
  325.     return fRet;
  326.     }
  327. //End CHAPTER21MOD
  328.  
  329.  
  330.  
  331. /*
  332.  * CPatronDoc::FDirtyGet
  333.  *
  334.  * Purpose:
  335.  *  Returns the current dirty status of the document.
  336.  *
  337.  * Parameters:
  338.  *  None
  339.  *
  340.  * Return Value:
  341.  *  BOOL            TRUE if the file is clean, FALSE otherwise.
  342.  */
  343.  
  344. BOOL CPatronDoc::FDirtyGet()
  345.     {
  346.     BOOL    fPageDirty;
  347.  
  348.     fPageDirty=m_pPG->FIsDirty();
  349.     return m_fDirty | fPageDirty;
  350.     }
  351.  
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.  * CPatronDoc::Delete
  358.  *
  359.  * Purpose:
  360.  *  Removed the current object from the document.
  361.  *
  362.  * Paramters:
  363.  *  None
  364.  *
  365.  * Return Value:
  366.  *  None
  367.  */
  368.  
  369. void CPatronDoc::Delete(void)
  370.     {
  371.     if (NULL!=m_pPG)
  372.         m_pPG->TenantDestroy();
  373.  
  374.     CoFreeUnusedLibraries();
  375.     return;
  376.     }
  377.  
  378.  
  379.  
  380.  
  381.  
  382. /*
  383.  * CPatronDoc::FQueryObjectSelected
  384.  *
  385.  * Purpose:
  386.  *  Returns whether or not there is an object selected in this
  387.  *  document for Cut, Copy, Delete functions.
  388.  *
  389.  * Parameters:
  390.  *  hMenu           HMENU of the Edit menu.
  391.  *
  392.  * Return Value:
  393.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  394.  */
  395.  
  396. BOOL CPatronDoc::FQueryObjectSelected(HMENU hMenu)
  397.     {
  398.     return m_pPG->FQueryObjectSelected(hMenu);
  399.     }
  400.  
  401.  
  402.  
  403.  
  404.  
  405. /*
  406.  * CPatronDoc::Load
  407.  *
  408.  * Purpose:
  409.  *  Loads a given document without any user interface overwriting
  410.  *  the previous contents of the editor.
  411.  *
  412.  * Parameters:
  413.  *  fChangeFile     BOOL indicating if we're to update the window
  414.  *                  title and the filename from using this file.
  415.  *  pszFile         LPTSTR to the filename to load.  Could be NULL
  416.  *                  for an untitled document.
  417.  *
  418.  * Return Value:
  419.  *  UINT            An error value from DOCERR_*
  420.  */
  421.  
  422. UINT CPatronDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  423.     {
  424.     RECT        rc;
  425.     LPSTORAGE   pIStorage;
  426.     HRESULT     hr;
  427.     CLSID       clsID;
  428.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
  429.                     | STGM_SHARE_EXCLUSIVE;
  430.     //CHAPTER21MOD
  431.     LPMONIKER   pmk;
  432.     //End CHAPTER21MOD
  433.  
  434.     if (NULL==pszFile)
  435.         {
  436.         //Create a new temp file.
  437.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE
  438.             | STGM_DELETEONRELEASE, 0, &pIStorage);
  439.  
  440.         //Mark this our class since we check with ReadClassStg.
  441.         if (SUCCEEDED(hr))
  442.             WriteClassStg(pIStorage, CLSID_PatronPages);
  443.         }
  444.     else
  445.         {
  446.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  447.         }
  448.  
  449.     if (FAILED(hr))
  450.         return DOCERR_COULDNOTOPEN;
  451.  
  452.     //Check if this is our type of file and exit if not.
  453.     hr=ReadClassStg(pIStorage, &clsID);
  454.  
  455.     if (FAILED(hr) || CLSID_PatronPages!=clsID)
  456.         {
  457.         pIStorage->Release();
  458.         return DOCERR_READFAILURE;
  459.         }
  460.  
  461.     //Attempt to create our contained Pages window.
  462.     m_pPG=new CPages(m_hInst, m_cf);
  463.     GetClientRect(m_hWnd, &rc);
  464.  
  465.     if (!m_pPG->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  466.         , ID_PAGES, NULL))
  467.         {
  468.         pIStorage->Release();
  469.         return DOCERR_READFAILURE;
  470.         }
  471.  
  472.     //CHAPTER21MOD
  473.     /*
  474.      * This moniker registration insures that all the file opening
  475.      * sequence will see this instance of the document as running
  476.      * and be able to communicate with it.  This is so a link to
  477.      * an embedding on the same page of this document will hook
  478.      * up correctly.
  479.      */
  480.     if (NULL!=pszFile)
  481.         {
  482.         CreateFileMoniker(pszFile, &pmk);
  483.  
  484.         if (NULL!=pmk)
  485.             {
  486.             //This will be revoked and re-registered in Rename below
  487.             INOLE_RegisterAsRunning(this, pmk, 0, &m_dwRegROT);
  488.             pmk->Release();
  489.             }
  490.         }
  491.     //End CHAPTER21MOD
  492.  
  493.     if (!m_pPG->StorageSet(pIStorage, FALSE, (NULL==pszFile)))
  494.         {
  495.         pIStorage->Release();
  496.         return DOCERR_READFAILURE;
  497.         }
  498.  
  499.     //Open the window up for drag-drop
  500.     m_pDropTarget=new CDropTarget(this);
  501.  
  502.     if (NULL!=m_pDropTarget)
  503.         {
  504.         m_pDropTarget->AddRef();
  505.         CoLockObjectExternal(m_pDropTarget, TRUE, FALSE);
  506.         RegisterDragDrop(m_hWnd, m_pDropTarget);
  507.         }
  508.  
  509.     m_pIStorage=pIStorage;
  510.     Rename(pszFile);
  511.  
  512.     //Do initial setup if new file, otherwise Pages handles things.
  513.     if (NULL==pszFile)
  514.         {
  515.         //Go initialize the Pages for the default printer.
  516.         if (!PrinterSetup(NULL, TRUE))
  517.             return DOCERR_COULDNOTOPEN;
  518.  
  519.         //Go create an initial page.
  520.         m_pPG->PageInsert(0);
  521.         }
  522.     else
  523.         {
  524.         //Can't change an already saved configuration
  525.         m_fPrintSetup=FALSE;
  526.         }
  527.  
  528.     FDirtySet(FALSE);
  529.     return DOCERR_NONE;
  530.     }
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538. /*
  539.  * CPatronDoc::Save
  540.  *
  541.  * Purpose:
  542.  *  Writes the file to a known filename, requiring that the user
  543.  *  has previously used FileOpen or FileSaveAs in order to have
  544.  *  a filename.
  545.  *
  546.  * Parameters:
  547.  *  uType           UINT indicating the type of file the user
  548.  *                  requested to save in the File Save As dialog.
  549.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  550.  *                  current name.
  551.  *
  552.  * Return Value:
  553.  *  UINT            An error value from DOCERR_*
  554.  */
  555.  
  556. UINT CPatronDoc::Save(UINT uType, LPTSTR pszFile)
  557.     {
  558.     HRESULT     hr;
  559.     LPSTORAGE   pIStorage;
  560.  
  561.     //Save or Save As with the same file is just a commit.
  562.     if (NULL==pszFile
  563.         || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  564.         {
  565.         WriteFmtUserTypeStg(m_pIStorage, m_cf
  566.             , PSZ(IDS_CLIPBOARDFORMAT));
  567.  
  568.         //Insure pages are up to date.
  569.         m_pPG->StorageUpdate(FALSE);
  570.  
  571.         //Commit everyting
  572.         m_pIStorage->Commit(STGC_DEFAULT);
  573.  
  574.         FDirtySet(FALSE);
  575.         return DOCERR_NONE;
  576.         }
  577.  
  578.     /*
  579.      * When we're given a name, open the storage, creating it new
  580.      * if it does not exist or overwriting the old one.  Then CopyTo
  581.      * from the current to the new, Commit the new, Release the old.
  582.      */
  583.  
  584.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  585.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  586.  
  587.     if (FAILED(hr))
  588.         return DOCERR_COULDNOTOPEN;
  589.  
  590.     WriteClassStg(pIStorage, CLSID_PatronPages);
  591.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  592.  
  593.     //Insure all pages are up-to-date.
  594.     m_pPG->StorageUpdate(TRUE);
  595.  
  596.     //This also copies the CLSID we stuff in here on file creation.
  597.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  598.  
  599.     if (FAILED(hr))
  600.         {
  601.         SCODE       sc;
  602.  
  603.         pIStorage->Release();
  604.         sc=GetScode(hr);
  605.  
  606.         /*
  607.          * If we failed because of low memory, use IRootStorage
  608.          * to switch into the new file.
  609.          */
  610.         if (E_OUTOFMEMORY==sc)
  611.             {
  612.             LPROOTSTORAGE        pIRoot;
  613.  
  614.             //Delete file we already created
  615.             DeleteFile(pszFile);
  616.  
  617.             if (FAILED(m_pIStorage->QueryInterface
  618.                 (IID_IRootStorage, (PPVOID)&pIRoot)))
  619.                 return DOCERR_WRITEFAILURE;
  620.  
  621.            #ifdef WIN32ANSI
  622.             OLECHAR     szTemp[MAX_PATH];
  623.  
  624.             MultiByteToWideChar(CP_ACP, 0, pszFile, -1, szTemp, MAX_PATH);
  625.             hr=pIRoot->SwitchToFile(szTemp);
  626.            #else
  627.             hr=pIRoot->SwitchToFile(pszFile);
  628.            #endif
  629.             pIRoot->Release();
  630.  
  631.             if (FAILED(hr))
  632.                 return DOCERR_WRITEFAILURE;
  633.  
  634.             //If successful, the Commit below finishes the save.
  635.             pIStorage=m_pIStorage;
  636.             m_pIStorage->AddRef();    //Matches Release below
  637.             }
  638.         }
  639.  
  640.     //CHAPTER21MOD
  641.     if (m_fRename)
  642.         Rename(pszFile);    //Update caption bar.
  643.     //End CHAPTER21MOD
  644.  
  645.     pIStorage->Commit(STGC_DEFAULT);
  646.  
  647.     /*
  648.      * Revert changes on the original storage.  If this was a temp
  649.      * file, it's deleted since we used STGM_DELETEONRELEASE.
  650.      */
  651.     m_pIStorage->Release();
  652.  
  653.     //Make this new storage current
  654.     m_pIStorage=pIStorage;
  655.     m_pPG->StorageSet(pIStorage, TRUE, FALSE);
  656.  
  657.     FDirtySet(FALSE);
  658.  
  659.     return DOCERR_NONE;
  660.     }
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669. /*
  670.  * CPatronDoc::Clip
  671.  *
  672.  * Purpose:
  673.  *  Places a private format, a metafile, and a bitmap of the display
  674.  *  on the clipboard, optionally implementing Cut by deleting the
  675.  *  data in the current window after rendering.
  676.  *
  677.  * Parameters:
  678.  *  hWndFrame       HWND of the main window.
  679.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  680.  *
  681.  * Return Value:
  682.  *  BOOL            TRUE if successful, FALSE otherwise.
  683.  */
  684.  
  685. BOOL CPatronDoc::Clip(HWND hWndFrame, BOOL fCut)
  686.     {
  687.     if (NULL==m_pPG)
  688.         return FALSE;
  689.  
  690.     return m_pPG->TenantClip(fCut);
  691.     }
  692.  
  693.  
  694.  
  695.  
  696.  
  697. /*
  698.  * CPatronDoc::Paste
  699.  *
  700.  * Purpose:
  701.  *  Retrieves the private data format from the clipboard and sets it
  702.  *  to the current figure in the editor window.
  703.  *
  704.  *  Note that if this function is called, then the clipboard format
  705.  *  is available because the Paste menu item is only enabled if the
  706.  *  format is present.
  707.  *
  708.  * Parameters:
  709.  *  hWndFrame       HWND of the main window.
  710.  *
  711.  * Return Value:
  712.  *  BOOL            TRUE if successful, FALSE otherwise.
  713.  */
  714.  
  715. BOOL CPatronDoc::Paste(HWND hWndFrame)
  716.     {
  717.     LPDATAOBJECT    pIDataObject;
  718.     BOOL            fRet=FALSE;
  719.     FORMATETC       fe;
  720.     TENANTTYPE      tType;
  721.  
  722.     if (NULL==m_pPG)
  723.         return FALSE;
  724.  
  725.     if (FAILED(OleGetClipboard(&pIDataObject)))
  726.         return FALSE;
  727.  
  728.     //Go get type and format we *can* paste, then actually paste it.
  729.     if (FQueryPasteFromData(pIDataObject, &fe, &tType))
  730.         {
  731.         fRet=PasteFromData(pIDataObject, &fe, tType, NULL
  732.             , 0L, TRUE);
  733.         }
  734.  
  735.     pIDataObject->Release();
  736.     return fRet;
  737.     }
  738.  
  739.  
  740.  
  741.  
  742. /*
  743.  * CPatronDoc::FQueryPaste
  744.  *
  745.  * Purpose:
  746.  *  Determines if we can paste data from the clipboard.
  747.  *
  748.  * Parameters:
  749.  *  None
  750.  *
  751.  * Return Value:
  752.  *  BOOL            TRUE if data is available, FALSE otherwise.
  753.  */
  754.  
  755. BOOL CPatronDoc::FQueryPaste(void)
  756.     {
  757.     LPDATAOBJECT    pIDataObject;
  758.     BOOL            fRet;
  759.  
  760.     if (FAILED(OleGetClipboard(&pIDataObject)))
  761.         return FALSE;
  762.  
  763.     fRet=FQueryPasteFromData(pIDataObject, NULL, NULL);
  764.  
  765.     fRet |= FQueryPasteLinkFromData(pIDataObject, NULL, NULL);
  766.     pIDataObject->Release();
  767.     return fRet;
  768.     }
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775. /*
  776.  * CPatronDoc::PasteSpecial
  777.  *
  778.  * Purpose:
  779.  *  Retrieves a specific data format from the clipboard and sends
  780.  *  it to the editor window appropriately.
  781.  *
  782.  *  Note that if this function is called, then the appropriate
  783.  *  format is available because the Paste menu item is only
  784.  *  enabled if the format is present.
  785.  *
  786.  * Parameters:
  787.  *  hWndFrame       HWND of the main window
  788.  *
  789.  * Return Value:
  790.  *  BOOL            TRUE if successful, FALSE otherwise.
  791.  */
  792.  
  793. BOOL CPatronDoc::PasteSpecial(HWND hWndFrame)
  794.     {
  795.     OLEUIPASTESPECIAL   ps;
  796.     OLEUIPASTEENTRY     rgPaste[6];
  797.     UINT                rgcf[1];        //For ps.m_arrLinkTypes
  798.     DWORD               dwData=0;
  799.     UINT                uTemp;
  800.     BOOL                fRet=FALSE;
  801.  
  802.     if (NULL==m_pPG)
  803.         return FALSE;
  804.  
  805.     memset(&ps, 0, sizeof(ps));
  806.  
  807.     if (FAILED(OleGetClipboard(&ps.lpSrcDataObj)))
  808.         return FALSE;
  809.  
  810.     ps.cbStruct=sizeof(ps);
  811.     ps.hWndOwner=hWndFrame;
  812.  
  813.     ps.dwFlags=PSF_SELECTPASTE;
  814.     ps.arrPasteEntries=rgPaste;
  815.  
  816.     //Set up Paste Special descriptor arrays.
  817.     SETDefFormatEtc(rgPaste[0].fmtetc, m_cf, TYMED_HGLOBAL);
  818.     rgPaste[0].lpstrFormatName=PSZ(IDS_CLIPBOARDFORMAT);
  819.     rgPaste[0].lpstrResultText=PSZ(IDS_PASTEASPATRON);
  820.     rgPaste[0].dwFlags=OLEUIPASTE_PASTEONLY;
  821.  
  822.     //Embedded objects can be iconic displays if the user wants.
  823.     SETDefFormatEtc(rgPaste[1].fmtetc, m_cfEmbeddedObject
  824.         , TYMED_ISTORAGE);
  825.     rgPaste[1].lpstrFormatName=PSZ(IDS_PASTEOBJECT);
  826.     rgPaste[1].lpstrResultText=PSZ(IDS_PASTEASOBJECT);
  827.  
  828.     /*
  829.      * CAUTION:  Use OLEUI_PASTE with embedded objects or else
  830.      * this item will not show up in the dialog.  I learned this the
  831.      * hard way (that is, after about 6 hours of pulling hair!).
  832.      */
  833.     rgPaste[1].dwFlags=OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON;
  834.  
  835.  
  836.     SETDefFormatEtc(rgPaste[2].fmtetc,CF_METAFILEPICT,TYMED_MFPICT);
  837.     rgPaste[2].lpstrFormatName=PSZ(IDS_PASTEMETAFILE);
  838.     rgPaste[2].lpstrResultText=PSZ(IDS_PASTEASMETAFILE);
  839.     rgPaste[2].dwFlags=OLEUIPASTE_PASTEONLY;
  840.  
  841.     SETDefFormatEtc(rgPaste[3].fmtetc, CF_DIB, TYMED_HGLOBAL);
  842.     rgPaste[3].lpstrFormatName=PSZ(IDS_PASTEDIB);
  843.     rgPaste[3].lpstrResultText=PSZ(IDS_PASTEASDIB);
  844.     rgPaste[3].dwFlags=OLEUIPASTE_PASTEONLY;
  845.  
  846.     SETDefFormatEtc(rgPaste[4].fmtetc, CF_BITMAP, TYMED_GDI);
  847.     rgPaste[4].lpstrFormatName=PSZ(IDS_PASTEBITMAP);
  848.     rgPaste[4].lpstrResultText=PSZ(IDS_PASTEASBITMAP);
  849.     rgPaste[4].dwFlags=OLEUIPASTE_PASTEONLY;
  850.  
  851.     SETDefFormatEtc(rgPaste[5].fmtetc,m_cfLinkSource,TYMED_ISTREAM);
  852.     rgPaste[5].lpstrFormatName=PSZ(IDS_PASTELINK);
  853.     rgPaste[5].lpstrResultText=PSZ(IDS_PASTEASLINK);
  854.     rgPaste[5].dwFlags=OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON;
  855.  
  856.     //Types we can Paste Link from the clipboard.
  857.     rgcf[0]=m_cfLinkSource;
  858.     ps.arrLinkTypes=rgcf;
  859.     ps.cLinkTypes=1;
  860.     ps.cPasteEntries=6;
  861.  
  862.     uTemp=OleUIPasteSpecial(&ps);
  863.  
  864.     if (OLEUI_OK==uTemp)
  865.         {
  866.         UINT        i=ps.nSelectedIndex;
  867.         TENANTTYPE  tType;
  868.  
  869.         if (ps.fLink)
  870.             tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  871.         else
  872.             {
  873.             if (1==ps.nSelectedIndex)
  874.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  875.             else
  876.                 tType=TENANTTYPE_STATIC;
  877.             }
  878.  
  879.         //Handle iconic aspects...from links as well
  880.         if ((1==i || ps.fLink) && (PSF_CHECKDISPLAYASICON
  881.             & ps.dwFlags) && NULL!=ps.hMetaPict)
  882.             {
  883.             rgPaste[i].fmtetc.dwAspect=DVASPECT_ICON;
  884.             dwData=(DWORD)(UINT)ps.hMetaPict;
  885.             }
  886.  
  887.         fRet=PasteFromData(ps.lpSrcDataObj, &rgPaste[i].fmtetc
  888.             , tType, NULL, dwData, FALSE);
  889.  
  890.         //Always free this regardless of what we do with it.
  891.         INOLE_MetafilePictIconFree(ps.hMetaPict);
  892.         }
  893.  
  894.     ps.lpSrcDataObj->Release();
  895.     return fRet;
  896.     }
  897.  
  898.  
  899.  
  900.  
  901. /*
  902.  * CPatronDoc::FQueryPasteFromData
  903.  * (Protected)
  904.  *
  905.  * Purpose:
  906.  *  Determines if we can paste data from a data object.
  907.  *
  908.  * Parameters:
  909.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  910.  *  pFE             LPFORMATETC in which to return the first format
  911.  *                  we can use.  Ignored if NULL.
  912.  *  ptType          PTENANTTYPE in which to store the type of
  913.  *                  object we can paste.  Ignored if NULL.
  914.  *
  915.  * Return Value:
  916.  *  BOOL            TRUE if data is available, FALSE otherwise.
  917.  */
  918.  
  919. BOOL CPatronDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject
  920.     , LPFORMATETC pFE, PTENANTTYPE ptType)
  921.     {
  922.     FORMATETC       fe;
  923.     HRESULT         hr, hr2;
  924.  
  925.     if (NULL!=(LPVOID)ptType)
  926.         *ptType=TENANTTYPE_STATIC;
  927.  
  928.     //Any of our specific data here?
  929.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  930.     hr=pIDataObject->QueryGetData(&fe);
  931.  
  932.     //If embedded object data is available, set the appropriate type
  933.     hr2=OleQueryCreateFromData(pIDataObject);
  934.  
  935.     if (NOERROR==hr2)
  936.         {
  937.         if (NULL!=pFE)
  938.             {
  939.             /*
  940.              * Default to content.  Paste will use
  941.              * CFSTR_OBJECTDESCRIPTOR to figure the actual aspect.
  942.              */
  943.             SETDefFormatEtc(*pFE, m_cfEmbeddedObject
  944.                 , TYMED_ISTORAGE);
  945.             }
  946.  
  947.         if (NULL!=(LPVOID)ptType)
  948.             *ptType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  949.  
  950.         /*
  951.          * Return now if PatronObject wasn't available, otherwise
  952.          * break out so that pFE gets PatronObject format.
  953.          */
  954.         if (NOERROR!=hr)
  955.             return TRUE;
  956.         }
  957.  
  958.  
  959.     if (NOERROR!=hr && NOERROR!=hr2)
  960.         {
  961.         //Try metafile, DIB, then bitmap, setting fe each time
  962.         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  963.         hr=pIDataObject->QueryGetData(&fe);
  964.  
  965.         if (NOERROR!=hr)
  966.             {
  967.             SETDefFormatEtc(fe, CF_DIB, TYMED_HGLOBAL);
  968.             hr=pIDataObject->QueryGetData(&fe);
  969.  
  970.             if (NOERROR!=hr)
  971.                 {
  972.                 SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  973.                 hr=pIDataObject->QueryGetData(&fe);
  974.                 }
  975.             }
  976.         }
  977.  
  978.     if (NOERROR==hr && NULL!=pFE)
  979.         *pFE=fe;
  980.  
  981.     return (NOERROR==hr);
  982.     }
  983.  
  984.  
  985.  
  986.  
  987.  
  988. /*
  989.  * CPatronDoc::FQueryPasteLinkFromData
  990.  * (Protected)
  991.  *
  992.  * Purpose:
  993.  *  Determines if we can paste link from a data object.
  994.  *
  995.  * Parameters:
  996.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  997.  *  pFE             LPFORMATETC in which to return the first format
  998.  *                  we can use.  Ignored if NULL.
  999.  *  ptType          PTENANTTYPE in which to store the type of object
  1000.  *                  we can paste.  Ignored if NULL.
  1001.  *
  1002.  * Return Value:
  1003.  *  BOOL            TRUE if data is available, FALSE otherwise.
  1004.  */
  1005.  
  1006. BOOL CPatronDoc::FQueryPasteLinkFromData(LPDATAOBJECT pIDataObject
  1007.     , LPFORMATETC pFE, PTENANTTYPE ptType)
  1008.     {
  1009.     HRESULT         hr;
  1010.  
  1011.     if (NULL==pIDataObject)
  1012.         return FALSE;
  1013.  
  1014.     hr=OleQueryLinkFromData(pIDataObject);
  1015.  
  1016.     if (NOERROR!=hr)
  1017.         return FALSE;
  1018.  
  1019.     if (NULL!=pFE)
  1020.         SETDefFormatEtc(*pFE, m_cfLinkSource, TYMED_ISTREAM);
  1021.  
  1022.     if (NULL!=(LPVOID)ptType)
  1023.         *ptType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  1024.  
  1025.     return TRUE;
  1026.     }
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033. /*
  1034.  * CPatronDoc::PasteFromData
  1035.  * (Protected)
  1036.  *
  1037.  * Purpose:
  1038.  *  Retrieves the private data format from a data object and sets
  1039.  *  it to the current figure in the editor window.
  1040.  *
  1041.  * Parameters:
  1042.  *  pIDataObject    LPDATAOBJECT from which to paste.
  1043.  *  pFE             LPFORMATETC to use in the paste. Cannot be NULL.
  1044.  *  tType           TENANTTYPE to paste.
  1045.  *  ppo             PPATRONOBJECT containing placement data.
  1046.  *  dwData          DWORD extra data sensitive to tType
  1047.  *  fUseObjDesc     BOOL indicating to use CFSTR_OBJECTDESCRIPTOR
  1048.  *                  format for determining the aspect of the object
  1049.  *                  if the format is available.
  1050.  *
  1051.  * Return Value:
  1052.  *  BOOL            TRUE if successful, FALSE otherwise.
  1053.  */
  1054.  
  1055. BOOL CPatronDoc::PasteFromData(LPDATAOBJECT pIDataObject
  1056.     , LPFORMATETC pFE, TENANTTYPE tType, PPATRONOBJECT ppo
  1057.     , DWORD dwData, BOOL fUseObjDesc)
  1058.     {
  1059.     BOOL                fRet;
  1060.     HRESULT             hr;
  1061.     PATRONOBJECT        po;
  1062.     STGMEDIUM           stm;
  1063.     LPOBJECTDESCRIPTOR  pOD;
  1064.     FORMATETC           fe;
  1065.     BOOL                fRelease=FALSE;
  1066.  
  1067.     if (NULL==pFE)
  1068.         return FALSE;
  1069.  
  1070.     //If not given any placement data, see if we can retrieve it
  1071.     if (pFE->cfFormat==m_cf && NULL==ppo)
  1072.         {
  1073.         hr=pIDataObject->GetData(pFE, &stm);
  1074.  
  1075.         if (SUCCEEDED(hr))
  1076.             {
  1077.             ppo=(PPATRONOBJECT)GlobalLock(stm.hGlobal);
  1078.  
  1079.             po=*ppo;
  1080.             ppo=&po;
  1081.  
  1082.             //If there's an object here, make sure type is right.
  1083.             if (ppo->fe.cfFormat==m_cfEmbeddedObject)
  1084.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  1085.  
  1086.             if (ppo->fe.cfFormat==m_cfLinkSource)
  1087.                 tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  1088.  
  1089.             GlobalUnlock(stm.hGlobal);
  1090.             ReleaseStgMedium(&stm);
  1091.             }
  1092.         }
  1093.  
  1094.     /*
  1095.      * If we're told to look at CFSTR_OBJECTDESCRIPTOR, then try to get
  1096.      * the data and copy the aspect out of it.  We're not interested
  1097.      * in any other part of it, however.
  1098.      */
  1099.     if (fUseObjDesc)
  1100.         {
  1101.         SETDefFormatEtc(fe, m_cfObjectDescriptor, TYMED_HGLOBAL);
  1102.  
  1103.         hr=pIDataObject->GetData(&fe, &stm);
  1104.  
  1105.         if (FAILED(hr))
  1106.             {
  1107.             SETDefFormatEtc(fe, m_cfLinkSrcDescriptor
  1108.                 , TYMED_HGLOBAL);
  1109.             hr=pIDataObject->GetData(&fe, &stm);
  1110.             }
  1111.  
  1112.         if (SUCCEEDED(hr))
  1113.             {
  1114.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  1115.             pFE->dwAspect=pOD->dwDrawAspect;
  1116.  
  1117.             if (NULL!=ppo)
  1118.                 ppo->fe.dwAspect=pFE->dwAspect;
  1119.  
  1120.             GlobalUnlock(stm.hGlobal);
  1121.             ReleaseStgMedium(&stm);
  1122.  
  1123.             /*
  1124.              * Furthermore, if pFE->dwAspect is DVASPECT_ICON, get
  1125.              * the metafile which will always be the icon
  1126.              * representation.
  1127.              */
  1128.             SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  1129.                 , TYMED_MFPICT, -1);
  1130.  
  1131.             if (SUCCEEDED(pIDataObject->GetData(&fe, &stm)))
  1132.                 {
  1133.                 dwData=(DWORD)(UINT)stm.hGlobal;
  1134.                 fRelease=TRUE;
  1135.                 }
  1136.             }
  1137.         }
  1138.  
  1139.     fRet=m_pPG->TenantCreate(tType, pIDataObject, pFE, ppo, dwData);
  1140.  
  1141.     //Release the stm from the last GetData
  1142.     if (fRelease)
  1143.         ReleaseStgMedium(&stm);
  1144.  
  1145.     if (fRet)
  1146.         {
  1147.         //Disable Printer Setup once we've created a tenant.
  1148.         m_fPrintSetup=FALSE;
  1149.         FDirtySet(TRUE);
  1150.         }
  1151.  
  1152.     return fRet;
  1153.     }
  1154.  
  1155.  
  1156.  
  1157.  
  1158. /*
  1159.  * CPatronDoc::FQueryEnableEditLinks
  1160.  *
  1161.  * Purpose:
  1162.  *  Determines whether or not the Edit Links menu item should be
  1163.  *  enabled on the frame window menu.
  1164.  *
  1165.  * Parameters:
  1166.  *  None
  1167.  *
  1168.  * Return Value:
  1169.  *  BOOL            TRUE to enable the item, FALSE otherwise.
  1170.  */
  1171.  
  1172. BOOL CPatronDoc::FQueryEnableEditLinks(void)
  1173.     {
  1174.     return m_pPG->FQueryLinksInPage();
  1175.     }
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181. /*
  1182.  * CPatronDoc::EditLinks
  1183.  *
  1184.  * Purpose:
  1185.  *  Invokes the links dialog in which the end-user can manipulate
  1186.  *  all the links in the current page.
  1187.  *
  1188.  * Parameters:
  1189.  *  hWndFrame       HWND of the frame window to use as the dialog
  1190.  *                  parent.
  1191.  *
  1192.  * Return Value:
  1193.  *  BOOL            TRUE if the function was successful,
  1194.  *                  FALSE otherwise.
  1195.  */
  1196.  
  1197. BOOL CPatronDoc::EditLinks(HWND hWndFrame)
  1198.     {
  1199.     UINT                    uRet;
  1200.     OLEUIEDITLINKS          el;
  1201.     PCIOleUILinkContainer   pIUILinks;
  1202.  
  1203.     memset(&el, 0, sizeof(el));
  1204.     el.cbStruct=sizeof(el);
  1205.     el.hWndOwner=hWndFrame;
  1206.  
  1207.     if (!m_pPG->GetUILinkContainer(&pIUILinks))
  1208.         return FALSE;
  1209.  
  1210.     el.lpOleUILinkContainer=pIUILinks;
  1211.     uRet=OleUIEditLinks(&el);
  1212.  
  1213.     //Only the IOleUILinkContainer interface will know dirtying.
  1214.     m_fDirty=pIUILinks->m_fDirty;
  1215.  
  1216.     el.lpOleUILinkContainer->Release();
  1217.     return TRUE;
  1218.     }
  1219.  
  1220.  
  1221.  
  1222. /*
  1223.  * CPatronDoc::ShowOrQueryObjectTypes
  1224.  *
  1225.  * Purpose:
  1226.  *  If querying, we return whether or not ShowObjects is active
  1227.  *  in this document.  Otherwise pass-through to
  1228.  *  CPages::ShowObjectTypes.
  1229.  *
  1230.  * Parameters:
  1231.  *  fQuery          BOOL indicating query or set.
  1232.  *  fShow           BOOL indicating to show the type or not.
  1233.  *
  1234.  * Return Value:
  1235.  *  None
  1236.  */
  1237.  
  1238. BOOL CPatronDoc::ShowOrQueryObjectTypes(BOOL fQuery, BOOL fShow)
  1239.     {
  1240.     if (fQuery)
  1241.         return m_fShowTypes;
  1242.  
  1243.     m_fShowTypes=fShow;
  1244.     m_pPG->ShowObjectTypes(fShow);
  1245.     return TRUE;
  1246.     }
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253. /*
  1254.  * CPatronDoc::NewPage
  1255.  *
  1256.  * Purpose:
  1257.  *  Creates a new page in the document's pages control after the
  1258.  *  current page.
  1259.  *
  1260.  * Parameters:
  1261.  *  None
  1262.  *
  1263.  * Return Value:
  1264.  *  UINT            Index of the new page.
  1265.  */
  1266.  
  1267. UINT CPatronDoc::NewPage(void)
  1268.     {
  1269.     FDirtySet(TRUE);
  1270.     return m_pPG->PageInsert(0);
  1271.     }
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279. /*
  1280.  * CPatronDoc::DeletePage
  1281.  *
  1282.  * Purpose:
  1283.  *  Deletes the current page from the document.
  1284.  *
  1285.  * Parameters:
  1286.  *  None
  1287.  *
  1288.  * Return Value:
  1289.  *  UINT            Index of the now current page.
  1290.  */
  1291.  
  1292. UINT CPatronDoc::DeletePage(void)
  1293.     {
  1294.     FDirtySet(TRUE);
  1295.     return m_pPG->PageDelete(0);
  1296.     }
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304. /*
  1305.  * CPatronDoc::NextPage
  1306.  *
  1307.  * Purpose:
  1308.  *  Shows the next page in the pages window.
  1309.  *
  1310.  * Parameters:
  1311.  *  None
  1312.  *
  1313.  * Return Value:
  1314.  *  UINT            Index of the new page.
  1315.  */
  1316.  
  1317. UINT CPatronDoc::NextPage(void)
  1318.     {
  1319.     UINT        iPage;
  1320.  
  1321.     iPage=m_pPG->CurPageGet();
  1322.     return m_pPG->CurPageSet(++iPage);
  1323.     }
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331. /*
  1332.  * CPatronDoc::PreviousPage
  1333.  *
  1334.  * Purpose:
  1335.  *  Shows the previous page in the pages window.
  1336.  *
  1337.  * Parameters:
  1338.  *  None
  1339.  *
  1340.  * Return Value:
  1341.  *  UINT            Index of the new page.
  1342.  */
  1343.  
  1344. UINT CPatronDoc::PreviousPage(void)
  1345.     {
  1346.     UINT        iPage;
  1347.  
  1348.     //If iPage is zero, then we wrap around to the end.
  1349.     iPage=m_pPG->CurPageGet();
  1350.     return m_pPG->CurPageSet(--iPage);
  1351.     }
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358. /*
  1359.  * CPatronDoc::FirstPage
  1360.  *
  1361.  * Purpose:
  1362.  *  Shows the first page page in the pages window.
  1363.  *
  1364.  * Parameters:
  1365.  *  None
  1366.  *
  1367.  * Return Value:
  1368.  *  UINT            Index of the new page.
  1369.  */
  1370.  
  1371. UINT CPatronDoc::FirstPage(void)
  1372.     {
  1373.     return m_pPG->CurPageSet(0);
  1374.     }
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381. /*
  1382.  * CPatronDoc::LastPage
  1383.  *
  1384.  * Purpose:
  1385.  *  Shows the last page in the pages window.
  1386.  *
  1387.  * Parameters:
  1388.  *  None
  1389.  *
  1390.  * Return Value:
  1391.  *  UINT            Index of the last page.
  1392.  */
  1393.  
  1394. UINT CPatronDoc::LastPage(void)
  1395.     {
  1396.     return m_pPG->CurPageSet(NOVALUE);
  1397.     }
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405. /*
  1406.  * CPatronDoc::Rename
  1407.  *
  1408.  * Purpose:
  1409.  *  Overrides the normal rename to include notification of tenants
  1410.  *  in this document of the new name.  This is so embedded objects
  1411.  *  are told the correct name through IOleObject::SetHostNames.
  1412.  *
  1413.  * Parameters:
  1414.  *  pszFile         LPTSTR to the new filename.
  1415.  *
  1416.  * Return Value:
  1417.  *  None
  1418.  */
  1419.  
  1420. void CPatronDoc::Rename(LPTSTR pszFile)
  1421.     {
  1422.     LPMONIKER   pmk;
  1423.  
  1424.     //We don't need to change the base class, just augment...
  1425.     CDocument::Rename(pszFile);
  1426.  
  1427.     //CHAPTER21MOD
  1428.     //Unregister the old moniker (m_dwRegROT set to zero).
  1429.     INOLE_RevokeAsRunning(&m_dwRegROT);
  1430.  
  1431.     if (NULL==pszFile)
  1432.         return;
  1433.  
  1434.     CreateFileMoniker(pszFile, &pmk);
  1435.  
  1436.     if (NULL!=pmk)
  1437.         {
  1438.         LPMONIKER   pmkAll;
  1439.  
  1440.         INOLE_RegisterAsRunning(this, pmk
  1441.             , ROTFLAGS_REGISTRATIONKEEPSALIVE, &m_dwRegROT);
  1442.  
  1443.         //Give a moniker to linked objects in tenants.
  1444.         m_pPG->NotifyTenantsOfRename(pszFile, pmk);
  1445.  
  1446.         //Register a File!"\" wildcard moniker as well
  1447.         CreateItemMoniker(TEXT("!"), TEXT("\\"), &pmkAll);
  1448.  
  1449.         if (NULL!=pmkAll)
  1450.             {
  1451.             LPMONIKER   pmkWild;
  1452.  
  1453.             INOLE_RevokeAsRunning(&m_dwRegROTWild);
  1454.             pmk->ComposeWith(pmkAll, FALSE, &pmkWild);
  1455.  
  1456.             if (NULL!=pmkWild)
  1457.                 {
  1458.                 INOLE_RegisterAsRunning(this, pmkWild, 0
  1459.                     , &m_dwRegROTWild);
  1460.                 pmkWild->Release();
  1461.                 }
  1462.  
  1463.             pmkAll->Release();
  1464.             }
  1465.  
  1466.         //No need for us to hold on to this.
  1467.         pmk->Release();
  1468.         }
  1469.     //End CHAPTER21MOD
  1470.  
  1471.     return;
  1472.     }
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478. /*
  1479.  * CPatronDoc::InsertObject
  1480.  *
  1481.  * Purpose:
  1482.  *  Retrieves a CLSID or a filename from the Insert Object dialog
  1483.  *  box and creates an object using those identifiers.
  1484.  *
  1485.  * Parameters:
  1486.  *  hWndFrame       HWND of the main window
  1487.  *
  1488.  * Return Value:
  1489.  *  BOOL            TRUE if successful, FALSE otherwise.
  1490.  */
  1491.  
  1492. BOOL CPatronDoc::InsertObject(HWND hWndFrame)
  1493.     {
  1494.     OLEUIINSERTOBJECT   io;
  1495.     DWORD               dwData=0;
  1496.     TCHAR               szFile[CCHPATHMAX];
  1497.     UINT                uTemp;
  1498.     BOOL                fRet=FALSE;
  1499.  
  1500.     if (NULL==m_pPG)
  1501.         return FALSE;
  1502.  
  1503.     memset(&io, 0, sizeof(io));
  1504.  
  1505.     io.cbStruct=sizeof(io);
  1506.     io.hWndOwner=hWndFrame;
  1507.  
  1508.     szFile[0]=0;
  1509.     io.lpszFile=szFile;
  1510.     io.cchFile=CCHPATHMAX;
  1511.  
  1512.     //We now support linking, so remove the IOF_DISABLELINK flag.
  1513.     io.dwFlags=IOF_SELECTCREATENEW;
  1514.  
  1515.     uTemp=OleUIInsertObject(&io);
  1516.  
  1517.     if (OLEUI_OK==uTemp)
  1518.         {
  1519.         TENANTTYPE      tType;
  1520.         LPVOID          pv;
  1521.         FORMATETC       fe;
  1522.  
  1523.         SETDefFormatEtc(fe, 0, TYMED_NULL);
  1524.  
  1525.         if (io.dwFlags & IOF_SELECTCREATENEW)
  1526.             {
  1527.             tType=TENANTTYPE_EMBEDDEDOBJECT;
  1528.             pv=&io.clsid;
  1529.             }
  1530.         else
  1531.             {
  1532.             if (io.dwFlags & IOF_CHECKLINK)
  1533.                 tType=TENANTTYPE_LINKEDFILE;
  1534.             else
  1535.                 tType=TENANTTYPE_EMBEDDEDFILE;
  1536.  
  1537.             pv=szFile;
  1538.             }
  1539.  
  1540.         if ((io.dwFlags & IOF_CHECKDISPLAYASICON)
  1541.             && NULL!=io.hMetaPict)
  1542.             {
  1543.             fe.dwAspect=DVASPECT_ICON;
  1544.             dwData=(DWORD)(UINT)io.hMetaPict;
  1545.             }
  1546.  
  1547.         fRet=m_pPG->TenantCreate(tType, pv, &fe, NULL, dwData);
  1548.  
  1549.         //Free this regardless of what we do with it.
  1550.         INOLE_MetafilePictIconFree(io.hMetaPict);
  1551.  
  1552.         if (fRet)
  1553.             {
  1554.             //Disable Printer Setup once we've created a tenant.
  1555.             m_fPrintSetup=FALSE;
  1556.             FDirtySet(TRUE);
  1557.             }
  1558.         }
  1559.  
  1560.     return fRet;
  1561.     }
  1562.  
  1563.  
  1564.  
  1565.  
  1566. /*
  1567.  * CPatronDoc::ActivateObject
  1568.  *
  1569.  * Purpose:
  1570.  *  Executes a verb on the currently selected object.
  1571.  *
  1572.  * Parameters:
  1573.  *  iVerb           LONG of the selected verb.
  1574.  *
  1575.  * Return Value:
  1576.  *  None
  1577.  */
  1578.  
  1579. void CPatronDoc::ActivateObject(LONG iVerb)
  1580.     {
  1581.     m_pPG->ActivateObject(iVerb);
  1582.     return;
  1583.     }
  1584.  
  1585.  
  1586. /*
  1587.  * CPatronDoc::ConvertObject
  1588.  *
  1589.  * Purpose:
  1590.  *  Invokes the Convert dialog on the current object.  Here it's
  1591.  *  just a pass-through to the pages.
  1592.  *
  1593.  * Parameters:
  1594.  *  hWndFrame       HWND of the frame window.
  1595.  *
  1596.  * Return Value:
  1597.  *  BOOL            TRUE if the function is successful, FALSE otherwise.
  1598.  */
  1599.  
  1600. BOOL CPatronDoc::ConvertObject(HWND hWndFrame)
  1601.     {
  1602.     return m_pPG->ConvertObject(hWndFrame);
  1603.     }
  1604.