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 / chap12 / patron / document.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  20KB  |  935 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Patron Chapter 12
  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.  
  39.     //CHAPTER12MOD
  40.     m_fPrintSetup=TRUE;
  41.     //End CHAPTER12MOD
  42.     return;
  43.     }
  44.  
  45.  
  46. CPatronDoc::~CPatronDoc(void)
  47.     {
  48.     if (NULL!=m_pPG)
  49.         delete m_pPG;
  50.  
  51.     ReleaseInterface(m_pIStorage);
  52.  
  53.     //CHAPTER12MOD
  54.     CoFreeUnusedLibraries();
  55.     //CHAPTER12MOD
  56.     return;
  57.     }
  58.  
  59.  
  60.  
  61.  
  62.  
  63. /*
  64.  * CPatronDoc::Init
  65.  *
  66.  * Purpose:
  67.  *  Initializes an already created document window.  The client
  68.  *  actually creates the window for us, then passes that here for
  69.  *  further initialization.
  70.  *
  71.  * Parameters:
  72.  *  pDI             PDOCUMENTINIT containing initialization
  73.  *                  parameters.
  74.  *
  75.  * Return Value:
  76.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  77.  */
  78.  
  79. BOOL CPatronDoc::Init(PDOCUMENTINIT pDI)
  80.     {
  81.     //Change the stringtable range to our customization.
  82.     pDI->idsMin=IDS_DOCUMENTMIN;
  83.     pDI->idsMax=IDS_DOCUMENTMAX;
  84.  
  85.     //Do default initialization
  86.     if (!CDocument::Init(pDI))
  87.         return FALSE;
  88.  
  89.     //Pages are created when we get a Load later.
  90.     return TRUE;
  91.     }
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CPatronDoc::FMessageHook
  100.  *
  101.  * Purpose:
  102.  *  Processes WM_SIZE for the document so we can resize the Pages
  103.  *  window.
  104.  *
  105.  * Parameters:
  106.  *  <WndProc Parameters>
  107.  *  pLRes           LRESULT * in which to store the return
  108.  *                  value for the message.
  109.  *
  110.  * Return Value:
  111.  *  BOOL            TRUE to prevent further processing,
  112.  *                  FALSE otherwise.
  113.  */
  114.  
  115. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  116.     , LPARAM lParam, LRESULT *pLRes)
  117.     {
  118.     UINT        dx, dy;
  119.     RECT        rc;
  120.  
  121.     *pLRes=0;
  122.  
  123.     //Eat to prevent flickering
  124.     if (WM_ERASEBKGND==iMsg)
  125.         return TRUE;
  126.  
  127.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  128.         {
  129.         dx=LOWORD(lParam);
  130.         dy=HIWORD(lParam);
  131.  
  132.         if (SIZE_MINIMIZED!=wParam)
  133.             {
  134.             //Resize Pages window to fit the new document size.
  135.             GetClientRect(hWnd, &rc);
  136.             m_pPG->RectSet(&rc, FALSE);
  137.             }
  138.         }
  139.  
  140.     /*
  141.      * We return FALSE even on WM_SIZE so we can let the default
  142.      * procedure handle maximized MDI child windows appropriately.
  143.      */
  144.     return FALSE;
  145.     }
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /*
  152.  * CPatronDoc::Clear
  153.  *
  154.  * Purpose:
  155.  *  Sets all contents in the document back to defaults with no
  156.  *  filename.
  157.  *
  158.  * Paramters:
  159.  *  None
  160.  *
  161.  * Return Value:
  162.  *  None
  163.  */
  164.  
  165. void CPatronDoc::Clear(void)
  166.     {
  167.     //Completely reset the pages
  168.     if (NULL!=m_pPG)
  169.         m_pPG->StorageSet(NULL, FALSE, FALSE);
  170.  
  171.     CDocument::Clear();
  172.     m_lVer=VERSIONCURRENT;
  173.     return;
  174.     }
  175.  
  176.  
  177.  
  178.  
  179. //CHAPTER12MOD
  180.  
  181. /*
  182.  * CPatronDoc::FDirtyGet
  183.  *
  184.  * Purpose:
  185.  *  Returns the current dirty status of the document.
  186.  *
  187.  * Parameters:
  188.  *  None
  189.  *
  190.  * Return Value:
  191.  *  BOOL            TRUE if the file is clean, FALSE otherwise.
  192.  */
  193.  
  194. BOOL CPatronDoc::FDirtyGet()
  195.     {
  196.     BOOL    fPageDirty;
  197.  
  198.     fPageDirty=m_pPG->FIsDirty();
  199.     return m_fDirty | fPageDirty;
  200.     }
  201.  
  202.  
  203.  
  204.  
  205.  
  206. /*
  207.  * CPatronDoc::Delete
  208.  *
  209.  * Purpose:
  210.  *  Removed the current object from the document.
  211.  *
  212.  * Paramters:
  213.  *  None
  214.  *
  215.  * Return Value:
  216.  *  None
  217.  */
  218.  
  219. void CPatronDoc::Delete(void)
  220.     {
  221.     if (NULL!=m_pPG)
  222.         m_pPG->TenantDestroy();
  223.  
  224.     CoFreeUnusedLibraries();
  225.     return;
  226.     }
  227.  
  228.  
  229.  
  230.  
  231. /*
  232.  * CPatronDoc::FQueryObjectSelected
  233.  *
  234.  * Purpose:
  235.  *  Returns whether or not there is an object selected in this
  236.  *  document for Cut, Copy, Delete functions.
  237.  *
  238.  * Parameters:
  239.  *  hMenu           HMENU of the Edit menu.
  240.  *
  241.  * Return Value:
  242.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  243.  */
  244.  
  245. BOOL CPatronDoc::FQueryObjectSelected(HMENU hMenu)
  246.     {
  247.     return m_pPG->FQueryObjectSelected(hMenu);
  248.     }
  249. //End CHAPTER12MOD
  250.  
  251.  
  252.  
  253. /*
  254.  * CPatronDoc::Load
  255.  *
  256.  * Purpose:
  257.  *  Loads a given document without any user interface overwriting
  258.  *  the previous contents of the editor.
  259.  *
  260.  * Parameters:
  261.  *  fChangeFile     BOOL indicating if we're to update the window
  262.  *                  title and the filename from using this file.
  263.  *  pszFile         LPTSTR to the filename to load.  Could be NULL
  264.  *                  for an untitled document.
  265.  *
  266.  * Return Value:
  267.  *  UINT            An error value from DOCERR_*
  268.  */
  269.  
  270. UINT CPatronDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  271.     {
  272.     RECT        rc;
  273.     LPSTORAGE   pIStorage;
  274.     HRESULT     hr;
  275.     CLSID       clsID;
  276.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
  277.                     | STGM_SHARE_EXCLUSIVE;
  278.  
  279.     if (NULL==pszFile)
  280.         {
  281.         //Create a new temp file.
  282.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE
  283.             | STGM_DELETEONRELEASE, 0, &pIStorage);
  284.  
  285.         //Mark this our class since we check with ReadClassStg.
  286.         if (SUCCEEDED(hr))
  287.             WriteClassStg(pIStorage, CLSID_PatronPages);
  288.         }
  289.     else
  290.         {
  291.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  292.         }
  293.  
  294.     if (FAILED(hr))
  295.         return DOCERR_COULDNOTOPEN;
  296.  
  297.     //Check if this is our type of file and exit if not.
  298.     hr=ReadClassStg(pIStorage, &clsID);
  299.  
  300.     if (FAILED(hr) || CLSID_PatronPages!=clsID)
  301.         {
  302.         pIStorage->Release();
  303.         return DOCERR_READFAILURE;
  304.         }
  305.  
  306.     //Attempt to create our contained Pages window.
  307.     //CHAPTER12MOD
  308.     m_pPG=new CPages(m_hInst, m_cf);
  309.     //End CHAPTER12MOD
  310.     GetClientRect(m_hWnd, &rc);
  311.  
  312.     if (!m_pPG->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  313.         , ID_PAGES, NULL))
  314.         {
  315.         pIStorage->Release();
  316.         return DOCERR_READFAILURE;
  317.         }
  318.  
  319.     if (!m_pPG->StorageSet(pIStorage, FALSE, (NULL==pszFile)))
  320.         {
  321.         pIStorage->Release();
  322.         return DOCERR_READFAILURE;
  323.         }
  324.  
  325.     m_pIStorage=pIStorage;
  326.     Rename(pszFile);
  327.  
  328.     //Do initial setup if new file, otherwise Pages handles things.
  329.     if (NULL==pszFile)
  330.         {
  331.         //Go initialize the Pages for the default printer.
  332.         if (!PrinterSetup(NULL, TRUE))
  333.             return DOCERR_COULDNOTOPEN;
  334.  
  335.         //Go create an initial page.
  336.         m_pPG->PageInsert(0);
  337.         }
  338.     //CHAPTER12MOD
  339.     else
  340.         {
  341.         //Can't change an already saved configuration
  342.         m_fPrintSetup=FALSE;
  343.         }
  344.     //End CHAPTER12MOD
  345.  
  346.     FDirtySet(FALSE);
  347.     return DOCERR_NONE;
  348.     }
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.  * CPatronDoc::Save
  358.  *
  359.  * Purpose:
  360.  *  Writes the file to a known filename, requiring that the user
  361.  *  has previously used FileOpen or FileSaveAs in order to have
  362.  *  a filename.
  363.  *
  364.  * Parameters:
  365.  *  uType           UINT indicating the type of file the user
  366.  *                  requested to save in the File Save As dialog.
  367.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  368.  *                  current name.
  369.  *
  370.  * Return Value:
  371.  *  UINT            An error value from DOCERR_*
  372.  */
  373.  
  374. UINT CPatronDoc::Save(UINT uType, LPTSTR pszFile)
  375.     {
  376.     HRESULT     hr;
  377.     LPSTORAGE   pIStorage;
  378.  
  379.     //Save or Save As with the same file is just a commit.
  380.     if (NULL==pszFile
  381.         || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  382.         {
  383.         WriteFmtUserTypeStg(m_pIStorage, m_cf
  384.             , PSZ(IDS_CLIPBOARDFORMAT));
  385.  
  386.         //Insure pages are up to date.
  387.         m_pPG->StorageUpdate(FALSE);
  388.  
  389.         //Commit everyting
  390.         m_pIStorage->Commit(STGC_DEFAULT);
  391.  
  392.         FDirtySet(FALSE);
  393.         return DOCERR_NONE;
  394.         }
  395.  
  396.     /*
  397.      * When we're given a name, open the storage, creating it new
  398.      * if it does not exist or overwriting the old one.  Then CopyTo
  399.      * from the current to the new, Commit the new, Release the old.
  400.      */
  401.  
  402.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  403.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  404.  
  405.     if (FAILED(hr))
  406.         return DOCERR_COULDNOTOPEN;
  407.  
  408.     WriteClassStg(pIStorage, CLSID_PatronPages);
  409.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  410.  
  411.     //Insure all pages are up-to-date.
  412.     m_pPG->StorageUpdate(TRUE);
  413.  
  414.     //This also copies the CLSID we stuff in here on file creation.
  415.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  416.  
  417.     if (FAILED(hr))
  418.         {
  419.         SCODE       sc;
  420.  
  421.         pIStorage->Release();
  422.         sc=GetScode(hr);
  423.  
  424.         /*
  425.          * If we failed because of low memory, use IRootStorage
  426.          * to switch into the new file.
  427.          */
  428.         if (E_OUTOFMEMORY==sc)
  429.             {
  430.             LPROOTSTORAGE        pIRoot;
  431.  
  432.             //Delete file we already created
  433.             DeleteFile(pszFile);
  434.  
  435.             if (FAILED(m_pIStorage->QueryInterface
  436.                 (IID_IRootStorage, (PPVOID)&pIRoot)))
  437.                 return DOCERR_WRITEFAILURE;
  438.  
  439.            #ifdef WIN32ANSI
  440.             OLECHAR     szTemp[MAX_PATH];
  441.  
  442.             MultiByteToWideChar(CP_ACP, 0, pszFile, -1, szTemp, MAX_PATH);
  443.             hr=pIRoot->SwitchToFile(szTemp);
  444.            #else
  445.             hr=pIRoot->SwitchToFile(pszFile);
  446.            #endif
  447.             pIRoot->Release();
  448.  
  449.             if (FAILED(hr))
  450.                 return DOCERR_WRITEFAILURE;
  451.  
  452.             //If successful, the Commit below finishes the save.
  453.             pIStorage=m_pIStorage;
  454.             m_pIStorage->AddRef();    //Matches Release below
  455.             }
  456.         }
  457.  
  458.     pIStorage->Commit(STGC_DEFAULT);
  459.  
  460.     /*
  461.      * Revert changes on the original storage.  If this was a temp
  462.      * file, it's deleted since we used STGM_DELETEONRELEASE.
  463.      */
  464.     m_pIStorage->Release();
  465.  
  466.     //Make this new storage current
  467.     m_pIStorage=pIStorage;
  468.     m_pPG->StorageSet(pIStorage, TRUE, FALSE);
  469.  
  470.     FDirtySet(FALSE);
  471.     Rename(pszFile);    //Update caption bar.
  472.  
  473.     return DOCERR_NONE;
  474.     }
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481. //CHAPTER12MOD
  482.  
  483.  
  484. /*
  485.  * CPatronDoc::Clip
  486.  *
  487.  * Purpose:
  488.  *  Places a private format, a metafile, and a bitmap of the display
  489.  *  on the clipboard, optionally implementing Cut by deleting the
  490.  *  data in the current window after rendering.
  491.  *
  492.  * Parameters:
  493.  *  hWndFrame       HWND of the main window.
  494.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  495.  *
  496.  * Return Value:
  497.  *  BOOL            TRUE if successful, FALSE otherwise.
  498.  */
  499.  
  500. BOOL CPatronDoc::Clip(HWND hWndFrame, BOOL fCut)
  501.     {
  502.     if (NULL==m_pPG)
  503.         return FALSE;
  504.  
  505.     return m_pPG->TenantClip(fCut);
  506.     }
  507.  
  508.  
  509.  
  510.  
  511.  
  512. /*
  513.  * CPatronDoc::Paste
  514.  *
  515.  * Purpose:
  516.  *  Retrieves the private data format from the clipboard and sets it
  517.  *  to the current figure in the editor window.
  518.  *
  519.  *  Note that if this function is called, then the clipboard format
  520.  *  is available because the Paste menu item is only enabled if the
  521.  *  format is present.
  522.  *
  523.  * Parameters:
  524.  *  hWndFrame       HWND of the main window.
  525.  *
  526.  * Return Value:
  527.  *  BOOL            TRUE if successful, FALSE otherwise.
  528.  */
  529.  
  530. BOOL CPatronDoc::Paste(HWND hWndFrame)
  531.     {
  532.     LPDATAOBJECT    pIDataObject;
  533.     BOOL            fRet=FALSE;
  534.     FORMATETC       fe;
  535.     TENANTTYPE      tType;
  536.  
  537.     if (NULL==m_pPG)
  538.         return FALSE;
  539.  
  540.     if (FAILED(OleGetClipboard(&pIDataObject)))
  541.         return FALSE;
  542.  
  543.     //Go get type and format we *can* paste, then actually paste it.
  544.     if (FQueryPasteFromData(pIDataObject, &fe, &tType))
  545.         fRet=PasteFromData(pIDataObject, &fe, tType, NULL, 0L);
  546.  
  547.     pIDataObject->Release();
  548.     return fRet;
  549.     }
  550.  
  551.  
  552.  
  553.  
  554. /*
  555.  * CPatronDoc::FQueryPaste
  556.  *
  557.  * Purpose:
  558.  *  Determines if we can paste data from the clipboard.
  559.  *
  560.  * Parameters:
  561.  *  None
  562.  *
  563.  * Return Value:
  564.  *  BOOL            TRUE if data is available, FALSE otherwise.
  565.  */
  566.  
  567. BOOL CPatronDoc::FQueryPaste(void)
  568.     {
  569.     LPDATAOBJECT    pIDataObject;
  570.     BOOL            fRet;
  571.  
  572.     if (FAILED(OleGetClipboard(&pIDataObject)))
  573.         return FALSE;
  574.  
  575.     fRet=FQueryPasteFromData(pIDataObject, NULL, NULL);
  576.     pIDataObject->Release();
  577.     return fRet;
  578.     }
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585. /*
  586.  * CPatronDoc::PasteSpecial
  587.  *
  588.  * Purpose:
  589.  *  Retrieves a specific data format from the clipboard and sends
  590.  *  it to the editor window appropriately.
  591.  *
  592.  *  Note that if this function is called, then the appropriate
  593.  *  format is available because the Paste menu item is only
  594.  *  enabled if the format is present.
  595.  *
  596.  * Parameters:
  597.  *  hWndFrame       HWND of the main window
  598.  *
  599.  * Return Value:
  600.  *  BOOL            TRUE if successful, FALSE otherwise.
  601.  */
  602.  
  603. BOOL CPatronDoc::PasteSpecial(HWND hWndFrame)
  604.     {
  605.     OLEUIPASTESPECIAL   ps;
  606.     OLEUIPASTEENTRY     rgPaste[4];
  607.     UINT                uTemp;
  608.     BOOL                fRet=FALSE;
  609.  
  610.     if (NULL==m_pPG)
  611.         return FALSE;
  612.  
  613.     memset(&ps, 0, sizeof(ps));
  614.  
  615.     if (FAILED(OleGetClipboard(&ps.lpSrcDataObj)))
  616.         return FALSE;
  617.  
  618.     ps.cbStruct=sizeof(ps);
  619.     ps.hWndOwner=hWndFrame;
  620.  
  621.     ps.dwFlags=PSF_SELECTPASTE;
  622.  
  623.     ps.arrPasteEntries=rgPaste;
  624.     ps.cPasteEntries=4;
  625.  
  626.     //Set up Paste Special descriptor arrays.
  627.     SETDefFormatEtc(rgPaste[0].fmtetc, m_cf, TYMED_HGLOBAL);
  628.     rgPaste[0].lpstrFormatName=PSZ(IDS_CLIPBOARDFORMAT);
  629.     rgPaste[0].lpstrResultText=PSZ(IDS_PASTEASPATRON);
  630.     rgPaste[0].dwFlags=OLEUIPASTE_PASTEONLY;
  631.  
  632.     SETDefFormatEtc(rgPaste[1].fmtetc,CF_METAFILEPICT,TYMED_MFPICT);
  633.     rgPaste[1].lpstrFormatName=PSZ(IDS_PASTEMETAFILE);
  634.     rgPaste[1].lpstrResultText=PSZ(IDS_PASTEASMETAFILE);
  635.     rgPaste[1].dwFlags=OLEUIPASTE_PASTEONLY;
  636.  
  637.     SETDefFormatEtc(rgPaste[2].fmtetc, CF_DIB, TYMED_HGLOBAL);
  638.     rgPaste[2].lpstrFormatName=PSZ(IDS_PASTEDIB);
  639.     rgPaste[2].lpstrResultText=PSZ(IDS_PASTEASDIB);
  640.     rgPaste[2].dwFlags=OLEUIPASTE_PASTEONLY;
  641.  
  642.     SETDefFormatEtc(rgPaste[3].fmtetc, CF_BITMAP, TYMED_GDI);
  643.     rgPaste[3].lpstrFormatName=PSZ(IDS_PASTEBITMAP);
  644.     rgPaste[3].lpstrResultText=PSZ(IDS_PASTEASBITMAP);
  645.     rgPaste[3].dwFlags=OLEUIPASTE_PASTEONLY;
  646.  
  647.     uTemp=OleUIPasteSpecial(&ps);
  648.  
  649.     if (OLEUI_OK==uTemp)
  650.         {
  651.         fRet=PasteFromData(ps.lpSrcDataObj
  652.             , &rgPaste[ps.nSelectedIndex].fmtetc
  653.             , TENANTTYPE_STATIC, NULL, 0L);
  654.         }
  655.  
  656.     ps.lpSrcDataObj->Release();
  657.     return fRet;
  658.     }
  659.  
  660.  
  661.  
  662.  
  663. /*
  664.  * CPatronDoc::FQueryPasteFromData
  665.  * (Protected)
  666.  *
  667.  * Purpose:
  668.  *  Determines if we can paste data from a data object.
  669.  *
  670.  * Parameters:
  671.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  672.  *  pFE             LPFORMATETC in which to return the first format
  673.  *                  we can use.  Ignored if NULL.
  674.  *  ptType          PTENANTTYPE in which to store the type of
  675.  *                  object we can paste.  Ignored if NULL.
  676.  *
  677.  * Return Value:
  678.  *  BOOL            TRUE if data is available, FALSE otherwise.
  679.  */
  680.  
  681. BOOL CPatronDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject
  682.     , LPFORMATETC pFE, PTENANTTYPE ptType)
  683.     {
  684.     FORMATETC       fe;
  685.     HRESULT         hr;
  686.  
  687.     if (NULL!=(LPVOID)ptType)
  688.         *ptType=TENANTTYPE_STATIC;
  689.  
  690.     //Any of our specific data here?
  691.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  692.     hr=pIDataObject->QueryGetData(&fe);
  693.  
  694.     if (NOERROR!=hr)
  695.         {
  696.         //Try metafile, DIB, then bitmap, setting fe each time
  697.         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  698.         hr=pIDataObject->QueryGetData(&fe);
  699.  
  700.         if (NOERROR!=hr)
  701.             {
  702.             SETDefFormatEtc(fe, CF_DIB, TYMED_HGLOBAL);
  703.             hr=pIDataObject->QueryGetData(&fe);
  704.  
  705.             if (NOERROR!=hr)
  706.                 {
  707.                 SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  708.                 hr=pIDataObject->QueryGetData(&fe);
  709.                 }
  710.             }
  711.         }
  712.  
  713.     if (NOERROR==hr && NULL!=pFE)
  714.         *pFE=fe;
  715.  
  716.     return (NOERROR==hr);
  717.     }
  718.  
  719.  
  720.  
  721.  
  722.  
  723. /*
  724.  * CPatronDoc::PasteFromData
  725.  * (Protected)
  726.  *
  727.  * Purpose:
  728.  *  Retrieves the private data format from a data object and sets
  729.  *  it to the current figure in the editor window.
  730.  *
  731.  * Parameters:
  732.  *  pIDataObject    LPDATAOBJECT from which to paste.
  733.  *  pFE             LPFORMATETC to use in the paste. Cannot be NULL.
  734.  *  tType           TENANTTYPE to paste.
  735.  *  ppo             PPATRONOBJECT containing placement data.
  736.  *  dwData          DWORD extra data sensitive to tType
  737.  *
  738.  * Return Value:
  739.  *  BOOL            TRUE if successful, FALSE otherwise.
  740.  */
  741.  
  742. BOOL CPatronDoc::PasteFromData(LPDATAOBJECT pIDataObject
  743.     , LPFORMATETC pFE, TENANTTYPE tType, PPATRONOBJECT ppo
  744.     , DWORD dwData)
  745.     {
  746.     BOOL            fRet;
  747.     HRESULT         hr;
  748.     PATRONOBJECT    po;
  749.     STGMEDIUM       stm;
  750.  
  751.     if (NULL==pFE)
  752.         return FALSE;
  753.  
  754.     //If not given any placement data, see if we can retrieve it
  755.     if (pFE->cfFormat==m_cf && NULL==ppo)
  756.         {
  757.         hr=pIDataObject->GetData(pFE, &stm);
  758.  
  759.         if (SUCCEEDED(hr))
  760.             {
  761.             ppo=(PPATRONOBJECT)GlobalLock(stm.hGlobal);
  762.  
  763.             po=*ppo;
  764.             ppo=&po;
  765.  
  766.             GlobalUnlock(stm.hGlobal);
  767.             ReleaseStgMedium(&stm);
  768.             }
  769.         }
  770.  
  771.     fRet=m_pPG->TenantCreate(tType, pIDataObject, pFE, ppo, dwData);
  772.  
  773.     if (fRet)
  774.         {
  775.         //Disable Printer Setup once we've created a tenant.
  776.         m_fPrintSetup=FALSE;
  777.         FDirtySet(TRUE);
  778.         }
  779.  
  780.     return fRet;
  781.     }
  782.  
  783. //End CHAPTER12MOD
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790. /*
  791.  * CPatronDoc::NewPage
  792.  *
  793.  * Purpose:
  794.  *  Creates a new page in the document's pages control after the
  795.  *  current page.
  796.  *
  797.  * Parameters:
  798.  *  None
  799.  *
  800.  * Return Value:
  801.  *  UINT            Index of the new page.
  802.  */
  803.  
  804. UINT CPatronDoc::NewPage(void)
  805.     {
  806.     FDirtySet(TRUE);
  807.     return m_pPG->PageInsert(0);
  808.     }
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816. /*
  817.  * CPatronDoc::DeletePage
  818.  *
  819.  * Purpose:
  820.  *  Deletes the current page from the document.
  821.  *
  822.  * Parameters:
  823.  *  None
  824.  *
  825.  * Return Value:
  826.  *  UINT            Index of the now current page.
  827.  */
  828.  
  829. UINT CPatronDoc::DeletePage(void)
  830.     {
  831.     FDirtySet(TRUE);
  832.     return m_pPG->PageDelete(0);
  833.     }
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841. /*
  842.  * CPatronDoc::NextPage
  843.  *
  844.  * Purpose:
  845.  *  Shows the next page in the pages window.
  846.  *
  847.  * Parameters:
  848.  *  None
  849.  *
  850.  * Return Value:
  851.  *  UINT            Index of the new page.
  852.  */
  853.  
  854. UINT CPatronDoc::NextPage(void)
  855.     {
  856.     UINT        iPage;
  857.  
  858.     iPage=m_pPG->CurPageGet();
  859.     return m_pPG->CurPageSet(++iPage);
  860.     }
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868. /*
  869.  * CPatronDoc::PreviousPage
  870.  *
  871.  * Purpose:
  872.  *  Shows the previous page in the pages window.
  873.  *
  874.  * Parameters:
  875.  *  None
  876.  *
  877.  * Return Value:
  878.  *  UINT            Index of the new page.
  879.  */
  880.  
  881. UINT CPatronDoc::PreviousPage(void)
  882.     {
  883.     UINT        iPage;
  884.  
  885.     //If iPage is zero, then we wrap around to the end.
  886.     iPage=m_pPG->CurPageGet();
  887.     return m_pPG->CurPageSet(--iPage);
  888.     }
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895. /*
  896.  * CPatronDoc::FirstPage
  897.  *
  898.  * Purpose:
  899.  *  Shows the first page page in the pages window.
  900.  *
  901.  * Parameters:
  902.  *  None
  903.  *
  904.  * Return Value:
  905.  *  UINT            Index of the new page.
  906.  */
  907.  
  908. UINT CPatronDoc::FirstPage(void)
  909.     {
  910.     return m_pPG->CurPageSet(0);
  911.     }
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918. /*
  919.  * CPatronDoc::LastPage
  920.  *
  921.  * Purpose:
  922.  *  Shows the last page in the pages window.
  923.  *
  924.  * Parameters:
  925.  *  None
  926.  *
  927.  * Return Value:
  928.  *  UINT            Index of the last page.
  929.  */
  930.  
  931. UINT CPatronDoc::LastPage(void)
  932.     {
  933.     return m_pPG->CurPageSet(NOVALUE);
  934.     }
  935.