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 / chap24 / patron / document.cpp < prev    next >
C/C++ Source or Header  |  1996-05-23  |  41KB  |  1,756 lines

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