home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP12.ZIP / PATRON / DOCUMENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-19  |  33.7 KB  |  1,484 lines

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