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 / chap17 / patron / document.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  28.1 KB  |  1,256 lines

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