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 / cocosmo / document.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  21KB  |  925 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Component Cosmo Chapter 12
  4.  *
  5.  * Implementation of the CCosmoDoc derivation of CDocument
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "cocosmo.h"
  16.  
  17.  
  18. /*
  19.  * CCosmoDoc::CCosmoDoc
  20.  * CCosmoDoc::~CCosmoDoc
  21.  *
  22.  * Constructor Parameters:
  23.  *  hInst           HINSTANCE of the application.
  24.  *  pFR             PCFrame of the frame object.
  25.  *  pAdv            PCDocumentAdviseSink to notify on events
  26.  */
  27.  
  28. CCosmoDoc::CCosmoDoc(HINSTANCE hInst, PCFrame pFR
  29.     , PCDocumentAdviseSink pAdv)
  30.     : CDocument(hInst, pFR, pAdv)
  31.     {
  32.     m_pPL=NULL;
  33.     m_pPLAdv=NULL;
  34.     m_uPrevSize=SIZE_RESTORED;
  35.     m_pIConnectPt=NULL;
  36.     m_dwCookie=0;
  37.  
  38.     m_pIStorage=NULL;
  39.     m_pp.psModel=PERSIST_UNKNOWN;
  40.     m_pp.pIP.pIPersistStorage=NULL; //Affects all pointers
  41.  
  42.     m_pImpIAdviseSink=NULL;
  43.     m_dwConn=0;
  44.  
  45.     //CHAPTER12MOD
  46.     m_pIDataClip=NULL;
  47.     //End CHAPTER12MOD
  48.     return;
  49.     }
  50.  
  51.  
  52. CCosmoDoc::~CCosmoDoc(void)
  53.     {
  54.     LPDATAOBJECT        pIDataObject;
  55.     HRESULT             hr;
  56.  
  57.     //CHAPTER12MOD
  58.     if (NULL!=m_pIDataClip)
  59.         m_pIDataClip->Release();
  60.     //End CHAPTER12MOD
  61.  
  62.     //Turn off the advise.
  63.     if (NULL!=m_pPL && 0!=m_dwConn)
  64.         {
  65.         hr=m_pPL->QueryInterface(IID_IDataObject
  66.             , (PPVOID)&pIDataObject);
  67.  
  68.         if (SUCCEEDED(hr))
  69.             {
  70.             pIDataObject->DUnadvise(m_dwConn);
  71.             pIDataObject->Release();
  72.             }
  73.         }
  74.  
  75.     DeleteInterfaceImp(m_pImpIAdviseSink);
  76.     ReleaseInterface(m_pp.pIP.pIPersistStorage);
  77.     ReleaseInterface(m_pIStorage);
  78.  
  79.     if (NULL!=m_pIConnectPt)
  80.         {
  81.         m_pIConnectPt->Unadvise(m_dwCookie);
  82.         ReleaseInterface(m_pIConnectPt);
  83.         }
  84.  
  85.     ReleaseInterface(m_pPL);
  86.     ReleaseInterface(m_pPLAdv);
  87.  
  88.     CoFreeUnusedLibraries();
  89.     return;
  90.     }
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /*
  98.  * CCosmoDoc::Init
  99.  *
  100.  * Purpose:
  101.  *  Initializes an already created document window.  The client
  102.  *  actually creates the window for us, then passes that here for
  103.  *  further initialization.
  104.  *
  105.  * Parameters:
  106.  *  pDI             PDOCUMENTINIT containing initialization
  107.  *                  parameters.
  108.  *
  109.  * Return Value:
  110.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  111.  */
  112.  
  113. BOOL CCosmoDoc::Init(PDOCUMENTINIT pDI)
  114.     {
  115.     RECT                        rc;
  116.     HRESULT                     hr;
  117.     IConnectionPointContainer  *pCPC;
  118.     FORMATETC                   fe;
  119.     LPDATAOBJECT                pIDataObject;
  120.  
  121.     //Change the stringtable range to our customization.
  122.     pDI->idsMin=IDS_DOCUMENTMIN;
  123.     pDI->idsMax=IDS_DOCUMENTMAX;
  124.  
  125.     //Do default initialization
  126.     if (!CDocument::Init(pDI))
  127.         return FALSE;
  128.  
  129.     //Create the Polyline Component
  130.     hr=CoCreateInstance(CLSID_Polyline10, NULL, CLSCTX_INPROC_SERVER
  131.         , IID_IPolyline10, (PPVOID)&m_pPL);
  132.  
  133.     if (FAILED(hr))
  134.         {
  135.         //Warn that we could not load the Polyline
  136.         MessageBox(pDI->hWndDoc, PSZ(IDS_NOPOLYLINE)
  137.             , PSZ(IDS_CAPTION), MB_OK);
  138.         return FALSE;
  139.         }
  140.  
  141.     //Initialize the contained Polyline which creates a window.
  142.     GetClientRect(m_hWnd, &rc);
  143.     InflateRect(&rc, -8, -8);
  144.  
  145.     if (FAILED(m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  146.         , ID_POLYLINE)))
  147.         return FALSE;
  148.  
  149.     //Set up an advise on the Polyline.
  150.     m_pPLAdv=new CPolylineAdviseSink(this);
  151.     m_pPLAdv->AddRef();
  152.  
  153.     if (SUCCEEDED(m_pPL->QueryInterface(IID_IConnectionPointContainer
  154.         , (PPVOID)&pCPC)))
  155.         {
  156.         //CHAPTER10MOD
  157.         if (SUCCEEDED(pCPC->FindConnectionPoint
  158.             (IID_IPolylineAdviseSink10, &m_pIConnectPt)))
  159.         //End CHAPTER10MOD
  160.             {
  161.             m_pIConnectPt->Advise((LPUNKNOWN)m_pPLAdv, &m_dwCookie);
  162.             }
  163.  
  164.         pCPC->Release();
  165.         }
  166.  
  167.     /*
  168.      * Check for the storage model being used in Polyline.
  169.      * Any InitNew member will be called from CCosmoDoc::Load.
  170.      */
  171.     hr=m_pPL->QueryInterface(IID_IPersistStorage
  172.         , (PPVOID)&m_pp.pIP.pIPersistStorage);
  173.  
  174.     if (SUCCEEDED(hr))
  175.         m_pp.psModel=PERSIST_STORAGE;
  176.     else
  177.         {
  178.         hr=m_pPL->QueryInterface(IID_IPersistStreamInit
  179.             , (PPVOID)&m_pp.pIP.pIPersistStreamInit);
  180.  
  181.         if (SUCCEEDED(hr))
  182.             m_pp.psModel=PERSIST_STREAMINIT;
  183.         else
  184.             {
  185.             hr=m_pPL->QueryInterface(IID_IPersistStream
  186.             , (PPVOID)&m_pp.pIP.pIPersistStream);
  187.  
  188.             if (SUCCEEDED(hr))
  189.                 m_pp.psModel=PERSIST_STREAM;
  190.             else
  191.                 return FALSE;
  192.             }
  193.         }
  194.  
  195.  
  196.     /*
  197.      * Create an IAdviseSink and send it to the Polyline's
  198.      * IDataObject with the clipboard format for the Polyline
  199.      * (as in IPOLY10.H).
  200.      */
  201.  
  202.     //This is a private macro.
  203.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  204.  
  205.     m_pImpIAdviseSink=new CImpIAdviseSink(this, this);
  206.  
  207.     if (NULL==m_pImpIAdviseSink)
  208.         return FALSE;
  209.  
  210.     //Set up an advise for the Polyline format
  211.     hr=m_pPL->QueryInterface(IID_IDataObject, (PPVOID)&pIDataObject);
  212.  
  213.     if (FAILED(hr))
  214.         return FALSE;
  215.  
  216.     pIDataObject->DAdvise(&fe, ADVF_NODATA, m_pImpIAdviseSink
  217.         , &m_dwConn);
  218.     pIDataObject->Release();
  219.  
  220.     return TRUE;
  221.     }
  222.  
  223.  
  224.  
  225.  
  226. //IUnknown interface for all others we implement in the document
  227.  
  228. /*
  229.  * CCosmoDoc::QueryInterface
  230.  * CCosmoDoc::AddRef
  231.  * CCosmoDoc::Release
  232.  *
  233.  * Purpose:
  234.  *  IUnknown members for the CCosmoDoc implementation.
  235.  */
  236.  
  237. STDMETHODIMP CCosmoDoc::QueryInterface(REFIID riid, PPVOID ppv)
  238.     {
  239.     *ppv=NULL;
  240.  
  241.     //The document is the unknown
  242.     if (IID_IUnknown==riid)
  243.         *ppv=(LPUNKNOWN)this;
  244.  
  245.     //Return contained interfaces for others.
  246.     if (IID_IPolylineAdviseSink10==riid)
  247.         *ppv=m_pPLAdv;
  248.  
  249.     if (IID_IAdviseSink==riid)
  250.         *ppv=m_pImpIAdviseSink;
  251.  
  252.     if (NULL!=*ppv)
  253.         {
  254.         ((LPUNKNOWN)*ppv)->AddRef();
  255.         return NOERROR;
  256.         }
  257.  
  258.     return ResultFromScode(S_FALSE);
  259.     }
  260.  
  261.  
  262. STDMETHODIMP_(ULONG) CCosmoDoc::AddRef(void)
  263.     {
  264.     return ++m_cRef;
  265.     }
  266.  
  267.  
  268. STDMETHODIMP_(ULONG) CCosmoDoc::Release(void)
  269.     {
  270.     return --m_cRef;
  271.     }
  272.  
  273.  
  274.  
  275.  
  276.  
  277. /*
  278.  * CCosmoDoc::FMessageHook
  279.  *
  280.  * Purpose:
  281.  *  Processes WM_SIZE for the document so we can resize
  282.  *  the Polyline.
  283.  *
  284.  * Parameters:
  285.  *  <WndProc Parameters>
  286.  *  pLRes           LRESULT * in which to store the return
  287.  *                  value for the message.
  288.  *
  289.  * Return Value:
  290.  *  BOOL            TRUE to prevent further processing,
  291.  *                  FALSE otherwise.
  292.  */
  293.  
  294. BOOL CCosmoDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  295.     , LPARAM lParam, LRESULT *pLRes)
  296.     {
  297.     UINT        dx, dy;
  298.     RECT        rc;
  299.  
  300.     *pLRes=0;
  301.  
  302.     //CHAPTER12MOD
  303.     if (WM_DESTROY==iMsg)
  304.         {
  305.         /*
  306.          * Flush the clipboard data object if it's still on the
  307.          * clipboard before the document window is destroyed which
  308.          * also destroys the polyline, which is a child.  Flushing
  309.          * now avoid errors that would occur if flushing happened
  310.          * at application shutdown, for the Polyline would still be
  311.          * alive but without a valid window.
  312.          */
  313.         if (NULL!=m_pIDataClip)
  314.             {
  315.             if (NOERROR==OleIsCurrentClipboard(m_pIDataClip))
  316.                 OleFlushClipboard();
  317.             }
  318.         }
  319.     //End CHAPTER12MOD
  320.  
  321.     if (WM_SIZE==iMsg)
  322.         {
  323.         //Don't effect the Polyline size to or from minimized state.
  324.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  325.             {
  326.             //When we change size, resize any Polyline we hold.
  327.             dx=LOWORD(lParam);
  328.             dy=HIWORD(lParam);
  329.  
  330.             /*
  331.              * If we are getting WM_SIZE in response to a Polyline
  332.              * notification, then don't resize the Polyline window
  333.              * again.
  334.              */
  335.             if (!m_fNoSize && NULL!=m_pPL)
  336.                 {
  337.                 //Resize the polyline to fit the new client
  338.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  339.                 m_pPL->RectSet(&rc, FALSE);
  340.  
  341.                 /*
  342.                  * We consider sizing something that makes the file
  343.                  * dirty, but not until we've finished the create
  344.                  * process, which is why we set fNoDirty to FALSE
  345.                  * in WM_CREATE since we get a WM_SIZE on the first
  346.                  * creation.
  347.                  */
  348.                 if (!m_fNoDirty)
  349.                     FDirtySet(TRUE);
  350.  
  351.                 SetRect(&rc, 0, 0, dx, dy);
  352.  
  353.                 if (NULL!=m_pAdv)
  354.                     m_pAdv->OnSizeChange(this, &rc);
  355.  
  356.                 m_fNoDirty=FALSE;
  357.                 }
  358.             }
  359.  
  360.         m_uPrevSize=wParam;
  361.         }
  362.  
  363.     /*
  364.      * We return FALSE even on WM_SIZE so we can let the default
  365.      * procedure handle maximized MDI child windows appropriately.
  366.      */
  367.     return FALSE;
  368.     }
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377. /*
  378.  * CCosmoDoc::Clear
  379.  *
  380.  * Purpose:
  381.  *  Sets all contents in the document back to defaults with
  382.  *  no filename.
  383.  *
  384.  * Paramters:
  385.  *  None
  386.  *
  387.  * Return Value:
  388.  *  None
  389.  */
  390.  
  391. void CCosmoDoc::Clear(void)
  392.     {
  393.     //Completely reset the polyline
  394.     m_pPL->New();
  395.  
  396.     CDocument::Clear();
  397.     return;
  398.     }
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405. /*
  406.  * CCosmoDoc::Load
  407.  *
  408.  * Purpose:
  409.  *  Loads a given document without any user interface overwriting
  410.  *  the previous contents of the Polyline window.  We do this by
  411.  *  opening the file and telling the Polyline to load itself from
  412.  *  that file.
  413.  *
  414.  * Parameters:
  415.  *  fChangeFile     BOOL indicating if we're to update the window
  416.  *                  title and the filename from using this file.
  417.  *  pszFile         LPTSTR to the filename to load, NULL if the file
  418.  *                  is new and untitled.
  419.  *
  420.  * Return Value:
  421.  *  UINT            An error value from DOCERR_*
  422.  */
  423.  
  424. UINT CCosmoDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  425.     {
  426.     HRESULT             hr;
  427.     LPSTORAGE           pIStorage;
  428.  
  429.     if (NULL==pszFile)
  430.         {
  431.         /*
  432.          * As a user of an IPersistStorage we have to provide all
  433.          * objects with an IStorage they can use for incremental
  434.          * access passing that storage to InitNew.  Here we create
  435.          * a temporary file that we don't bother holding on to.
  436.          * If the object doesn't use it, then our Release destroys
  437.          * it immediately.
  438.          */
  439.  
  440.         hr=StgCreateDocfile(NULL, STGM_DIRECT | STGM_READWRITE
  441.             | STGM_CREATE | STGM_DELETEONRELEASE
  442.             | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  443.  
  444.         if (FAILED(hr))
  445.             return DOCERR_COULDNOTOPEN;
  446.  
  447.         if (PERSIST_STORAGE==m_pp.psModel)
  448.             m_pp.pIP.pIPersistStorage->InitNew(pIStorage);
  449.         else
  450.             {
  451.             if (PERSIST_STREAMINIT==m_pp.psModel)
  452.                 m_pp.pIP.pIPersistStreamInit->InitNew();
  453.             }
  454.  
  455.         m_pIStorage=pIStorage;
  456.  
  457.         Rename(NULL);
  458.         return DOCERR_NONE;
  459.         }
  460.  
  461.     /*
  462.      * Open a storage and have the Polyline read its data
  463.      * using whatever persistence model it employs.
  464.      */
  465.     hr=StgOpenStorage(pszFile, NULL, STGM_DIRECT | STGM_READWRITE
  466.         | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
  467.  
  468.     if (FAILED(hr))
  469.         return DOCERR_COULDNOTOPEN;
  470.  
  471.     if (PERSIST_STORAGE==m_pp.psModel)
  472.         hr=m_pp.pIP.pIPersistStorage->Load(pIStorage);
  473.     else
  474.         {
  475.         LPSTREAM    pIStream;
  476.  
  477.         hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
  478.             | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  479.  
  480.         if (SUCCEEDED(hr))
  481.             {
  482.             //This also works for PERSIST_STREAMINIT
  483.             hr=m_pp.pIP.pIPersistStream->Load(pIStream);
  484.             pIStream->Release();
  485.             }
  486.         }
  487.  
  488.     m_pIStorage=pIStorage;
  489.  
  490.     if (FAILED(hr))
  491.         return DOCERR_READFAILURE;
  492.  
  493.     if (fChangeFile)
  494.         Rename(pszFile);
  495.  
  496.     //Importing a file makes things dirty
  497.     FDirtySet(!fChangeFile);
  498.  
  499.     return DOCERR_NONE;
  500.     }
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508. /*
  509.  * CCosmoDoc::Save
  510.  *
  511.  * Purpose:
  512.  *  Writes the file to a known filename, requiring that the user
  513.  *  has previously used FileOpen or FileSaveAs in order to have
  514.  *  a filename.
  515.  *
  516.  * Parameters:
  517.  *  uType           UINT indicating the type of file the user
  518.  *                  requested to save in the File Save As dialog.
  519.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  520.  *                  current name.
  521.  *
  522.  * Return Value:
  523.  *  UINT            An error value from DOCERR_*
  524.  */
  525.  
  526. UINT CCosmoDoc::Save(UINT uType, LPTSTR pszFile)
  527.     {
  528.     BOOL                fRename=TRUE;
  529.     HRESULT             hr;
  530.     LPSTORAGE           pIStorage;
  531.     BOOL                fSameAsLoad;
  532.  
  533.     //If Save or Save As under the same name, do Save.
  534.     if (NULL==pszFile || 0==lstrcmpi(pszFile, m_szFile))
  535.         {
  536.         fRename=FALSE;
  537.         pszFile=m_szFile;
  538.  
  539.         /*
  540.          * If we're saving to an existing storage, just pass
  541.          * the IStorage we have from Load along with TRUE
  542.          * in fSameAsLoad.
  543.          */
  544.  
  545.         fSameAsLoad=TRUE;
  546.         }
  547.     else
  548.         {
  549.         /*
  550.          * In Component Cosmo, we only deal with one version of
  551.          * data; all the code in Chapter 1 Cosmo that dealt with
  552.          * 1.0 and 2.0 files has been removed.
  553.          */
  554.  
  555.         hr=StgCreateDocfile(pszFile, STGM_DIRECT | STGM_READWRITE
  556.             | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  557.  
  558.         if (FAILED(hr))
  559.             return DOCERR_COULDNOTOPEN;
  560.  
  561.         //Tell the object to save into this new storage
  562.         fSameAsLoad=FALSE;
  563.  
  564.         //Update our variable
  565.         m_pIStorage->Release();
  566.         m_pIStorage=pIStorage;
  567.         }
  568.  
  569.     if (PERSIST_STORAGE==m_pp.psModel)
  570.         {
  571.         hr=m_pp.pIP.pIPersistStorage->Save(m_pIStorage, fSameAsLoad);
  572.  
  573.         if (SUCCEEDED(hr))
  574.             {
  575.             hr=m_pp.pIP.pIPersistStorage->SaveCompleted(fSameAsLoad
  576.                 ? NULL : m_pIStorage);
  577.             }
  578.         }
  579.     else
  580.         {
  581.         LPSTREAM    pIStream;
  582.  
  583.         hr=m_pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
  584.             | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE
  585.             , 0, 0, &pIStream);
  586.  
  587.         if (SUCCEEDED(hr))
  588.             {
  589.             //This also works for PERSIST_STREAMINIT
  590.             hr=m_pp.pIP.pIPersistStream->Save(pIStream, TRUE);
  591.             pIStream->Release();
  592.             }
  593.         }
  594.  
  595.  
  596.     if (FAILED(hr))
  597.         return DOCERR_WRITEFAILURE;
  598.  
  599.     //Saving makes us clean
  600.     FDirtySet(FALSE);
  601.  
  602.     if (fRename)
  603.         Rename(pszFile);
  604.  
  605.     return DOCERR_NONE;
  606.     }
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613. /*
  614.  * CCosmoDoc::Undo
  615.  *
  616.  * Purpose:
  617.  *  Reverses a previous action.
  618.  *
  619.  * Parameters:
  620.  *  None
  621.  *
  622.  * Return Value:
  623.  *  None
  624.  */
  625.  
  626. void CCosmoDoc::Undo(void)
  627.     {
  628.     m_pPL->Undo();
  629.     return;
  630.     }
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637. /*
  638.  * CCosmoDoc::Clip
  639.  *
  640.  * Purpose:
  641.  *  Places a private format, a metafile, and a bitmap of the display
  642.  *  on the clipboard, optionally implementing Cut by deleting the
  643.  *  data in the current window after rendering.
  644.  *
  645.  * Parameters:
  646.  *  hWndFrame       HWND of the main window.
  647.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  648.  *
  649.  * Return Value:
  650.  *  BOOL            TRUE if successful, FALSE otherwise.
  651.  */
  652.  
  653. BOOL CCosmoDoc::Clip(HWND hWndFrame, BOOL fCut)
  654.     {
  655.     //CHAPTER12MOD
  656.     PPOLYLINE               pPL;
  657.     LPDATAOBJECT            pDataSrc, pIDataObject;
  658.     FORMATETC               fe;
  659.     STGMEDIUM               stm;
  660.     BOOL                    fRet=TRUE;
  661.     HRESULT                 hr;
  662.     RECT                    rc;
  663.  
  664.     //Create a transfer Polyline Object
  665.     hr=CoCreateInstance(CLSID_Polyline10, NULL, CLSCTX_INPROC_SERVER
  666.         , IID_IPolyline10, (PPVOID)&pPL);
  667.  
  668.     if (FAILED(hr))
  669.         return FALSE;
  670.  
  671.     //Make the new transfer Polyline same size as the current one.
  672.     m_pPL->RectGet(&rc);
  673.  
  674.     if (FAILED(pPL->Init(m_hWnd, &rc, WS_CHILD, ID_POLYLINE)))
  675.         {
  676.         pPL->Release();
  677.         return FALSE;
  678.         }
  679.  
  680.     /*
  681.      * Now that we have the new object, get IDataObject interfaces
  682.      * on both that one and the new one we hold, then copy the
  683.      * data from the current to the new.
  684.      */
  685.  
  686.     m_pPL->QueryInterface(IID_IDataObject, (PPVOID)&pDataSrc);
  687.  
  688.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  689.     fRet=SUCCEEDED(pDataSrc->GetData(&fe, &stm));
  690.     pDataSrc->Release();
  691.  
  692.     if (!fRet)
  693.         {
  694.         pPL->Release();
  695.         return FALSE;
  696.         }
  697.  
  698.     pPL->QueryInterface(IID_IDataObject, (PPVOID)&pIDataObject);
  699.     pPL->Release();
  700.  
  701.     pIDataObject->SetData(&fe, &stm, TRUE);
  702.  
  703.     fRet=SUCCEEDED(OleSetClipboard(pIDataObject));
  704.  
  705.     /*
  706.      * OleSetClipboard will call AddRef on pDataDst, and we
  707.      * still own a reference count ourselves.  We thus save
  708.      * this pointer so we can call OleIsCurrentClipboard and
  709.      * OleFlushClipboard when the document is destroyed.
  710.      */
  711.  
  712.     if (NULL!=m_pIDataClip)
  713.         m_pIDataClip->Release();
  714.  
  715.     m_pIDataClip=pIDataObject;
  716.  
  717.     //Delete our current data if a "cut" succeeded.
  718.     if (fRet && fCut)
  719.         {
  720.         m_pPL->New();
  721.         FDirtySet(TRUE);
  722.         }
  723.  
  724.     return fRet;
  725.     //End CHAPTER12MOD
  726.     }
  727.  
  728.  
  729.  
  730. //CHAPTER12MOD
  731. //CCosmoDoc::RenderFormat no longer necessary.
  732. //End CHAPTER12MOD
  733.  
  734.  
  735. /*
  736.  * CCosmoDoc::FQueryPaste
  737.  *
  738.  * Purpose:
  739.  *  Determines if we can paste data from the clipboard.
  740.  *
  741.  * Parameters:
  742.  *  None
  743.  *
  744.  * Return Value:
  745.  *  BOOL            TRUE if data is available, FALSE otherwise.
  746.  */
  747.  
  748. BOOL CCosmoDoc::FQueryPaste(void)
  749.     {
  750.     //CHAPTER12MOD
  751.     LPDATAOBJECT    pIDataObject;
  752.     FORMATETC       fe;
  753.     BOOL            fRet;
  754.  
  755.     if (FAILED(OleGetClipboard(&pIDataObject)))
  756.         return FALSE;
  757.  
  758.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  759.     fRet=(NOERROR==pIDataObject->QueryGetData(&fe));
  760.  
  761.     pIDataObject->Release();
  762.     return fRet;
  763.     //End CHAPTER12MOD
  764.     }
  765.  
  766.  
  767.  
  768.  
  769.  
  770. /*
  771.  * CCosmoDoc::Paste
  772.  *
  773.  * Purpose:
  774.  *  Retrieves the private data format from the clipboard and sets it
  775.  *  to the current figure in the editor window.
  776.  *
  777.  *  Note that if this function is called, then the clipboard format
  778.  *  is available because the Paste menu item is only enabled if the
  779.  *  format is present.
  780.  *
  781.  * Parameters:
  782.  *  hWndFrame       HWND of the main window.
  783.  *
  784.  * Return Value:
  785.  *  BOOL            TRUE if successful, FALSE otherwise.
  786.  */
  787.  
  788. BOOL CCosmoDoc::Paste(HWND hWndFrame)
  789.     {
  790.     //CHAPTER12MOD
  791.     LPDATAOBJECT    pIDataObject;
  792.     FORMATETC       fe;
  793.     STGMEDIUM       stm;
  794.     BOOL            fRet;
  795.  
  796.     if (FAILED(OleGetClipboard(&pIDataObject)))
  797.         return FALSE;
  798.  
  799.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  800.     fRet=SUCCEEDED(pIDataObject->GetData(&fe, &stm));
  801.     pIDataObject->Release();
  802.  
  803.     if (!fRet || NULL==stm.hGlobal)
  804.         return FALSE;
  805.  
  806.     //Send the data to the Polyline now.
  807.     m_pPL->QueryInterface(IID_IDataObject, (PPVOID)&pIDataObject);
  808.     pIDataObject->SetData(&fe, &stm, TRUE);
  809.     pIDataObject->Release();
  810.  
  811.     FDirtySet(TRUE);
  812.     //End CHAPTER12MOD
  813.  
  814.     return TRUE;
  815.     }
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822. /*
  823.  * CCosmoDoc::ColorSet
  824.  *
  825.  * Purpose:
  826.  *  Changes a color used in our contained Polyline.
  827.  *
  828.  * Parameters:
  829.  *  iColor          UINT index of the color to change.
  830.  *  cr              COLORREF new color.
  831.  *
  832.  * Return Value:
  833.  *  COLORREF        Previous color for the given index.
  834.  */
  835.  
  836. COLORREF CCosmoDoc::ColorSet(UINT iColor, COLORREF cr)
  837.     {
  838.     COLORREF    crRet;
  839.  
  840.     m_pPL->ColorSet(iColor, cr, &crRet);
  841.     return crRet;
  842.     }
  843.  
  844.  
  845.  
  846.  
  847.  
  848. /*
  849.  * CCosmoDoc::ColorGet
  850.  *
  851.  * Purpose:
  852.  *  Retrieves a color currently in use in the Polyline.
  853.  *
  854.  * Parameters:
  855.  *  iColor          UINT index of the color to retrieve.
  856.  *
  857.  * Return Value:
  858.  *  COLORREF        Current color for the given index.
  859.  */
  860.  
  861. COLORREF CCosmoDoc::ColorGet(UINT iColor)
  862.     {
  863.     COLORREF    crRet;
  864.  
  865.     m_pPL->ColorGet(iColor, &crRet);
  866.     return crRet;
  867.     }
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874. /*
  875.  * CCosmoDoc::LineStyleSet
  876.  *
  877.  * Purpose:
  878.  *  Changes the line style currently used in the Polyline
  879.  *
  880.  * Parameters:
  881.  *  iStyle          UINT index of the new line style to use.
  882.  *
  883.  * Return Value:
  884.  *  UINT            Previous line style.
  885.  */
  886.  
  887. UINT CCosmoDoc::LineStyleSet(UINT iStyle)
  888.     {
  889.     UINT    i;
  890.  
  891.     m_pPL->LineStyleSet(iStyle, &i);
  892.     return i;
  893.     }
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901. /*
  902.  * CCosmoDoc::LineStyleGet
  903.  *
  904.  * Purpose:
  905.  *  Retrieves the line style currently used in the Polyline
  906.  *
  907.  * Parameters:
  908.  *  None
  909.  *
  910.  * Return Value:
  911.  *  UINT            Current line style.
  912.  */
  913.  
  914.  
  915. UINT CCosmoDoc::LineStyleGet(void)
  916.     {
  917.     UINT    i=0;
  918.  
  919.     //m_pPL might not be valid yet.
  920.     if (NULL!=m_pPL)
  921.         m_pPL->LineStyleGet(&i);
  922.  
  923.     return i;
  924.     }
  925.