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

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