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 / chap10 / cocosmo / document.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  20.2 KB  |  935 lines

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