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 / chap13 / cocosmo / document.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  26KB  |  1,115 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Component Cosmo Chapter 13
  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.     m_pIDataClip=NULL;
  45.  
  46.     //CHAPTER13MOD
  47.     m_pDropTarget=NULL;
  48.     m_fDragSource=FALSE;
  49.     //End CHAPTER13MOD
  50.  
  51.     return;
  52.     }
  53.  
  54.  
  55. CCosmoDoc::~CCosmoDoc(void)
  56.     {
  57.     LPDATAOBJECT        pIDataObject;
  58.     HRESULT             hr;
  59.  
  60.     if (NULL!=m_pIDataClip)
  61.         m_pIDataClip->Release();
  62.  
  63.     //Turn off the advise.
  64.     if (NULL!=m_pPL && 0!=m_dwConn)
  65.         {
  66.         hr=m_pPL->QueryInterface(IID_IDataObject
  67.             , (PPVOID)&pIDataObject);
  68.  
  69.         if (SUCCEEDED(hr))
  70.             {
  71.             pIDataObject->DUnadvise(m_dwConn);
  72.             pIDataObject->Release();
  73.             }
  74.         }
  75.  
  76.     DeleteInterfaceImp(m_pImpIAdviseSink);
  77.     ReleaseInterface(m_pp.pIP.pIPersistStorage);
  78.     ReleaseInterface(m_pIStorage);
  79.  
  80.     if (NULL!=m_pIConnectPt)
  81.         {
  82.         m_pIConnectPt->Unadvise(m_dwCookie);
  83.         ReleaseInterface(m_pIConnectPt);
  84.         }
  85.  
  86.     ReleaseInterface(m_pPL);
  87.     ReleaseInterface(m_pPLAdv);
  88.  
  89.     CoFreeUnusedLibraries();
  90.     return;
  91.     }
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CCosmoDoc::Init
  100.  *
  101.  * Purpose:
  102.  *  Initializes an already created document window.  The client
  103.  *  actually creates the window for us, then passes that here for
  104.  *  further initialization.
  105.  *
  106.  * Parameters:
  107.  *  pDI             PDOCUMENTINIT containing initialization
  108.  *                  parameters.
  109.  *
  110.  * Return Value:
  111.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  112.  */
  113.  
  114. BOOL CCosmoDoc::Init(PDOCUMENTINIT pDI)
  115.     {
  116.     RECT                        rc;
  117.     HRESULT                     hr;
  118.     IConnectionPointContainer  *pCPC;
  119.     FORMATETC                   fe;
  120.     LPDATAOBJECT                pIDataObject;
  121.  
  122.     //Change the stringtable range to our customization.
  123.     pDI->idsMin=IDS_DOCUMENTMIN;
  124.     pDI->idsMax=IDS_DOCUMENTMAX;
  125.  
  126.     //Do default initialization
  127.     if (!CDocument::Init(pDI))
  128.         return FALSE;
  129.  
  130.     //Create the Polyline Component
  131.     hr=CoCreateInstance(CLSID_Polyline10, NULL, CLSCTX_INPROC_SERVER
  132.         , IID_IPolyline10, (PPVOID)&m_pPL);
  133.  
  134.     if (FAILED(hr))
  135.         {
  136.         //Warn that we could not load the Polyline
  137.         MessageBox(pDI->hWndDoc, PSZ(IDS_NOPOLYLINE)
  138.             , PSZ(IDS_CAPTION), MB_OK);
  139.         return FALSE;
  140.         }
  141.  
  142.     //Initialize the contained Polyline which creates a window.
  143.     GetClientRect(m_hWnd, &rc);
  144.     InflateRect(&rc, -8, -8);
  145.  
  146.     if (FAILED(m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  147.         , ID_POLYLINE)))
  148.         return FALSE;
  149.  
  150.     //Set up an advise on the Polyline.
  151.     m_pPLAdv=new CPolylineAdviseSink(this);
  152.     m_pPLAdv->AddRef();
  153.  
  154.     if (SUCCEEDED(m_pPL->QueryInterface(IID_IConnectionPointContainer
  155.         , (PPVOID)&pCPC)))
  156.         {
  157.         //CHAPTER10MOD
  158.         if (SUCCEEDED(pCPC->FindConnectionPoint
  159.             (IID_IPolylineAdviseSink10, &m_pIConnectPt)))
  160.         //End CHAPTER10MOD
  161.             {
  162.             m_pIConnectPt->Advise((LPUNKNOWN)m_pPLAdv, &m_dwCookie);
  163.             }
  164.  
  165.         pCPC->Release();
  166.         }
  167.  
  168.     /*
  169.      * Check for the storage model being used in Polyline.
  170.      * Any InitNew member will be called from CCosmoDoc::Load.
  171.      */
  172.     hr=m_pPL->QueryInterface(IID_IPersistStorage
  173.         , (PPVOID)&m_pp.pIP.pIPersistStorage);
  174.  
  175.     if (SUCCEEDED(hr))
  176.         m_pp.psModel=PERSIST_STORAGE;
  177.     else
  178.         {
  179.         hr=m_pPL->QueryInterface(IID_IPersistStreamInit
  180.             , (PPVOID)&m_pp.pIP.pIPersistStreamInit);
  181.  
  182.         if (SUCCEEDED(hr))
  183.             m_pp.psModel=PERSIST_STREAMINIT;
  184.         else
  185.             {
  186.             hr=m_pPL->QueryInterface(IID_IPersistStream
  187.             , (PPVOID)&m_pp.pIP.pIPersistStream);
  188.  
  189.             if (SUCCEEDED(hr))
  190.                 m_pp.psModel=PERSIST_STREAM;
  191.             else
  192.                 return FALSE;
  193.             }
  194.         }
  195.  
  196.  
  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.  
  221.     //CHAPTER13MOD
  222.     m_pDropTarget=new CDropTarget(this);
  223.  
  224.     if (NULL!=m_pDropTarget)
  225.         {
  226.         m_pDropTarget->AddRef();
  227.         CoLockObjectExternal(m_pDropTarget, TRUE, FALSE);
  228.         RegisterDragDrop(m_hWnd, m_pDropTarget);
  229.         }
  230.     //End CHAPTER13MOD
  231.  
  232.     return TRUE;
  233.     }
  234.  
  235.  
  236.  
  237.  
  238. //IUnknown interface for all others we implement in the document
  239.  
  240. /*
  241.  * CCosmoDoc::QueryInterface
  242.  * CCosmoDoc::AddRef
  243.  * CCosmoDoc::Release
  244.  *
  245.  * Purpose:
  246.  *  IUnknown members for the CCosmoDoc implementation.
  247.  */
  248.  
  249. STDMETHODIMP CCosmoDoc::QueryInterface(REFIID riid, PPVOID ppv)
  250.     {
  251.     *ppv=NULL;
  252.  
  253.     //The document is the unknown
  254.     if (IID_IUnknown==riid)
  255.         *ppv=(LPUNKNOWN)this;
  256.  
  257.     //Return contained interfaces for others.
  258.     if (IID_IPolylineAdviseSink10==riid)
  259.         *ppv=m_pPLAdv;
  260.  
  261.     if (IID_IAdviseSink==riid)
  262.         *ppv=m_pImpIAdviseSink;
  263.  
  264.     if (NULL!=*ppv)
  265.         {
  266.         ((LPUNKNOWN)*ppv)->AddRef();
  267.         return NOERROR;
  268.         }
  269.  
  270.     return ResultFromScode(S_FALSE);
  271.     }
  272.  
  273.  
  274. STDMETHODIMP_(ULONG) CCosmoDoc::AddRef(void)
  275.     {
  276.     return ++m_cRef;
  277.     }
  278.  
  279.  
  280. STDMETHODIMP_(ULONG) CCosmoDoc::Release(void)
  281.     {
  282.     return --m_cRef;
  283.     }
  284.  
  285.  
  286.  
  287.  
  288.  
  289. /*
  290.  * CCosmoDoc::FMessageHook
  291.  *
  292.  * Purpose:
  293.  *  Processes WM_SIZE for the document so we can resize
  294.  *  the Polyline.
  295.  *
  296.  * Parameters:
  297.  *  <WndProc Parameters>
  298.  *  pLRes           LRESULT * in which to store the return
  299.  *                  value for the message.
  300.  *
  301.  * Return Value:
  302.  *  BOOL            TRUE to prevent further processing,
  303.  *                  FALSE otherwise.
  304.  */
  305.  
  306. BOOL CCosmoDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  307.     , LPARAM lParam, LRESULT *pLRes)
  308.     {
  309.     UINT        dx, dy;
  310.     RECT        rc;
  311.  
  312.     *pLRes=0;
  313.  
  314.     if (WM_DESTROY==iMsg)
  315.         {
  316.         /*
  317.          * Flush the clipboard data object if it's still on the
  318.          * clipboard before the document window is destroyed which
  319.          * also destroys the polyline, which is a child.  Flushing
  320.          * now avoid errors that would occur if flushing happened
  321.          * at application shutdown, for the Polyline would still be
  322.          * alive but without a valid window.
  323.          */
  324.         if (NULL!=m_pIDataClip)
  325.             {
  326.             if (NOERROR==OleIsCurrentClipboard(m_pIDataClip))
  327.                 OleFlushClipboard();
  328.             }
  329.  
  330.         //CHAPTER13MOD
  331.         /*
  332.          * We have to revoke the drop target here because the window
  333.          * will be destroyed and the property forcefully removed
  334.          * before we could do this in the destructor.
  335.          */
  336.         if (NULL!=m_pDropTarget)
  337.             {
  338.             RevokeDragDrop(m_hWnd);
  339.             CoLockObjectExternal(m_pDropTarget, FALSE, TRUE);
  340.             m_pDropTarget->Release();
  341.             }
  342.         //End CHAPTER13MOD
  343.         }
  344.  
  345.     if (WM_SIZE==iMsg)
  346.         {
  347.         //Don't effect the Polyline size to or from minimized state.
  348.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  349.             {
  350.             //When we change size, resize any Polyline we hold.
  351.             dx=LOWORD(lParam);
  352.             dy=HIWORD(lParam);
  353.  
  354.             /*
  355.              * If we are getting WM_SIZE in response to a Polyline
  356.              * notification, then don't resize the Polyline window
  357.              * again.
  358.              */
  359.             if (!m_fNoSize && NULL!=m_pPL)
  360.                 {
  361.                 //Resize the polyline to fit the new client
  362.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  363.                 m_pPL->RectSet(&rc, FALSE);
  364.  
  365.                 /*
  366.                  * We consider sizing something that makes the file
  367.                  * dirty, but not until we've finished the create
  368.                  * process, which is why we set fNoDirty to FALSE
  369.                  * in WM_CREATE since we get a WM_SIZE on the first
  370.                  * creation.
  371.                  */
  372.                 if (!m_fNoDirty)
  373.                     FDirtySet(TRUE);
  374.  
  375.                 SetRect(&rc, 0, 0, dx, dy);
  376.  
  377.                 if (NULL!=m_pAdv)
  378.                     m_pAdv->OnSizeChange(this, &rc);
  379.  
  380.                 m_fNoDirty=FALSE;
  381.                 }
  382.             }
  383.  
  384.         m_uPrevSize=wParam;
  385.         }
  386.  
  387.     //CHAPTER13MOD
  388.     if (WM_LBUTTONDOWN==iMsg)
  389.         {
  390.         LPDROPSOURCE    pIDropSource;
  391.         LPDATAOBJECT    pIDataObject;
  392.         HRESULT         hr;
  393.         SCODE           sc;
  394.         DWORD           dwEffect;
  395.  
  396.         pIDropSource=new CDropSource(this);
  397.  
  398.         if (NULL==pIDropSource)
  399.             return FALSE;
  400.  
  401.         pIDropSource->AddRef();
  402.         m_fDragSource=TRUE;
  403.  
  404.         //Go get the data and start the ball rolling.
  405.         pIDataObject=TransferObjectCreate();
  406.  
  407.         if (NULL!=pIDataObject)
  408.             {
  409.             hr=DoDragDrop(pIDataObject, pIDropSource
  410.                 , DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
  411.  
  412.             pIDataObject->Release();
  413.             sc=GetScode(hr);
  414.             }
  415.         else
  416.             sc=E_FAIL;
  417.  
  418.         pIDropSource->Release();
  419.         m_fDragSource=FALSE;
  420.  
  421.         if (DRAGDROP_S_DROP==sc && DROPEFFECT_MOVE==dwEffect)
  422.             {
  423.             m_pPL->New();
  424.             FDirtySet(TRUE);
  425.             }
  426.  
  427.         return TRUE;
  428.         }
  429.     //End CHAPTER13MOD
  430.  
  431.  
  432.     /*
  433.      * We return FALSE even on WM_SIZE so we can let the default
  434.      * procedure handle maximized MDI child windows appropriately.
  435.      */
  436.     return FALSE;
  437.     }
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446. /*
  447.  * CCosmoDoc::Clear
  448.  *
  449.  * Purpose:
  450.  *  Sets all contents in the document back to defaults with
  451.  *  no filename.
  452.  *
  453.  * Paramters:
  454.  *  None
  455.  *
  456.  * Return Value:
  457.  *  None
  458.  */
  459.  
  460. void CCosmoDoc::Clear(void)
  461.     {
  462.     //Completely reset the polyline
  463.     m_pPL->New();
  464.  
  465.     CDocument::Clear();
  466.     return;
  467.     }
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474. /*
  475.  * CCosmoDoc::Load
  476.  *
  477.  * Purpose:
  478.  *  Loads a given document without any user interface overwriting
  479.  *  the previous contents of the Polyline window.  We do this by
  480.  *  opening the file and telling the Polyline to load itself from
  481.  *  that file.
  482.  *
  483.  * Parameters:
  484.  *  fChangeFile     BOOL indicating if we're to update the window
  485.  *                  title and the filename from using this file.
  486.  *  pszFile         LPTSTR to the filename to load, NULL if the file
  487.  *                  is new and untitled.
  488.  *
  489.  * Return Value:
  490.  *  UINT            An error value from DOCERR_*
  491.  */
  492.  
  493. UINT CCosmoDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  494.     {
  495.     HRESULT             hr;
  496.     LPSTORAGE           pIStorage;
  497.  
  498.     if (NULL==pszFile)
  499.         {
  500.         /*
  501.          * As a user of an IPersistStorage we have to provide all
  502.          * objects with an IStorage they can use for incremental
  503.          * access passing that storage to InitNew.  Here we create
  504.          * a temporary file that we don't bother holding on to.
  505.          * If the object doesn't use it, then our Release destroys
  506.          * it immediately.
  507.          */
  508.  
  509.         hr=StgCreateDocfile(NULL, STGM_DIRECT | STGM_READWRITE
  510.             | STGM_CREATE | STGM_DELETEONRELEASE
  511.             | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  512.  
  513.         if (FAILED(hr))
  514.             return DOCERR_COULDNOTOPEN;
  515.  
  516.         if (PERSIST_STORAGE==m_pp.psModel)
  517.             m_pp.pIP.pIPersistStorage->InitNew(pIStorage);
  518.         else
  519.             {
  520.             if (PERSIST_STREAMINIT==m_pp.psModel)
  521.                 m_pp.pIP.pIPersistStreamInit->InitNew();
  522.             }
  523.  
  524.         m_pIStorage=pIStorage;
  525.  
  526.         Rename(NULL);
  527.         return DOCERR_NONE;
  528.         }
  529.  
  530.     /*
  531.      * Open a storage and have the Polyline read its data
  532.      * using whatever persistence model it employs.
  533.      */
  534.     hr=StgOpenStorage(pszFile, NULL, STGM_DIRECT | STGM_READWRITE
  535.         | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
  536.  
  537.     if (FAILED(hr))
  538.         return DOCERR_COULDNOTOPEN;
  539.  
  540.     if (PERSIST_STORAGE==m_pp.psModel)
  541.         hr=m_pp.pIP.pIPersistStorage->Load(pIStorage);
  542.     else
  543.         {
  544.         LPSTREAM    pIStream;
  545.  
  546.         hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
  547.             | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  548.  
  549.         if (SUCCEEDED(hr))
  550.             {
  551.             //This also works for PERSIST_STREAMINIT
  552.             hr=m_pp.pIP.pIPersistStream->Load(pIStream);
  553.             pIStream->Release();
  554.             }
  555.         }
  556.  
  557.     m_pIStorage=pIStorage;
  558.  
  559.     if (FAILED(hr))
  560.         return DOCERR_READFAILURE;
  561.  
  562.     if (fChangeFile)
  563.         Rename(pszFile);
  564.  
  565.     //Importing a file makes things dirty
  566.     FDirtySet(!fChangeFile);
  567.  
  568.     return DOCERR_NONE;
  569.     }
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577. /*
  578.  * CCosmoDoc::Save
  579.  *
  580.  * Purpose:
  581.  *  Writes the file to a known filename, requiring that the user
  582.  *  has previously used FileOpen or FileSaveAs in order to have
  583.  *  a filename.
  584.  *
  585.  * Parameters:
  586.  *  uType           UINT indicating the type of file the user
  587.  *                  requested to save in the File Save As dialog.
  588.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  589.  *                  current name.
  590.  *
  591.  * Return Value:
  592.  *  UINT            An error value from DOCERR_*
  593.  */
  594.  
  595. UINT CCosmoDoc::Save(UINT uType, LPTSTR pszFile)
  596.     {
  597.     BOOL                fRename=TRUE;
  598.     HRESULT             hr;
  599.     LPSTORAGE           pIStorage;
  600.     BOOL                fSameAsLoad;
  601.  
  602.     //If Save or Save As under the same name, do Save.
  603.     if (NULL==pszFile || 0==lstrcmpi(pszFile, m_szFile))
  604.         {
  605.         fRename=FALSE;
  606.         pszFile=m_szFile;
  607.  
  608.         /*
  609.          * If we're saving to an existing storage, just pass
  610.          * the IStorage we have from Load along with TRUE
  611.          * in fSameAsLoad.
  612.          */
  613.  
  614.         fSameAsLoad=TRUE;
  615.         }
  616.     else
  617.         {
  618.         /*
  619.          * In Component Cosmo, we only deal with one version of
  620.          * data; all the code in Chapter 1 Cosmo that dealt with
  621.          * 1.0 and 2.0 files has been removed.
  622.          */
  623.  
  624.         hr=StgCreateDocfile(pszFile, STGM_DIRECT | STGM_READWRITE
  625.             | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  626.  
  627.         if (FAILED(hr))
  628.             return DOCERR_COULDNOTOPEN;
  629.  
  630.         //Tell the object to save into this new storage
  631.         fSameAsLoad=FALSE;
  632.  
  633.         //Update our variable
  634.         m_pIStorage->Release();
  635.         m_pIStorage=pIStorage;
  636.         }
  637.  
  638.     if (PERSIST_STORAGE==m_pp.psModel)
  639.         {
  640.         hr=m_pp.pIP.pIPersistStorage->Save(m_pIStorage, fSameAsLoad);
  641.  
  642.         if (SUCCEEDED(hr))
  643.             {
  644.             hr=m_pp.pIP.pIPersistStorage->SaveCompleted(fSameAsLoad
  645.                 ? NULL : m_pIStorage);
  646.             }
  647.         }
  648.     else
  649.         {
  650.         LPSTREAM    pIStream;
  651.  
  652.         hr=m_pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
  653.             | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE
  654.             , 0, 0, &pIStream);
  655.  
  656.         if (SUCCEEDED(hr))
  657.             {
  658.             //This also works for PERSIST_STREAMINIT
  659.             hr=m_pp.pIP.pIPersistStream->Save(pIStream, TRUE);
  660.             pIStream->Release();
  661.             }
  662.         }
  663.  
  664.  
  665.     if (FAILED(hr))
  666.         return DOCERR_WRITEFAILURE;
  667.  
  668.     //Saving makes us clean
  669.     FDirtySet(FALSE);
  670.  
  671.     if (fRename)
  672.         Rename(pszFile);
  673.  
  674.     return DOCERR_NONE;
  675.     }
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682. /*
  683.  * CCosmoDoc::Undo
  684.  *
  685.  * Purpose:
  686.  *  Reverses a previous action.
  687.  *
  688.  * Parameters:
  689.  *  None
  690.  *
  691.  * Return Value:
  692.  *  None
  693.  */
  694.  
  695. void CCosmoDoc::Undo(void)
  696.     {
  697.     m_pPL->Undo();
  698.     return;
  699.     }
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706. /*
  707.  * CCosmoDoc::Clip
  708.  *
  709.  * Purpose:
  710.  *  Places a private format, a metafile, and a bitmap of the display
  711.  *  on the clipboard, optionally implementing Cut by deleting the
  712.  *  data in the current window after rendering.
  713.  *
  714.  * Parameters:
  715.  *  hWndFrame       HWND of the main window.
  716.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  717.  *
  718.  * Return Value:
  719.  *  BOOL            TRUE if successful, FALSE otherwise.
  720.  */
  721.  
  722. BOOL CCosmoDoc::Clip(HWND hWndFrame, BOOL fCut)
  723.     {
  724.     //CHAPTER13MOD
  725.     BOOL            fRet=TRUE;
  726.     LPDATAOBJECT    pIDataObject;
  727.  
  728.     pIDataObject=TransferObjectCreate();
  729.  
  730.     if (NULL==pIDataObject)
  731.         return FALSE;
  732.     //CHAPTER13MOD
  733.  
  734.     fRet=SUCCEEDED(OleSetClipboard(pIDataObject));
  735.  
  736.     if (NULL!=m_pIDataClip)
  737.         m_pIDataClip->Release();
  738.  
  739.     m_pIDataClip=pIDataObject;
  740.  
  741.     //Delete our current data if a "cut" succeeded.
  742.     if (fRet && fCut)
  743.         {
  744.         m_pPL->New();
  745.         FDirtySet(TRUE);
  746.         }
  747.  
  748.     return fRet;
  749.     }
  750.  
  751.  
  752.  
  753.  
  754.  
  755. /*
  756.  * CCosmoDoc::FQueryPaste
  757.  *
  758.  * Purpose:
  759.  *  Determines if we can paste data from the clipboard.
  760.  *
  761.  * Parameters:
  762.  *  None
  763.  *
  764.  * Return Value:
  765.  *  BOOL            TRUE if data is available, FALSE otherwise.
  766.  */
  767.  
  768. BOOL CCosmoDoc::FQueryPaste(void)
  769.     {
  770.     LPDATAOBJECT    pIDataObject;
  771.     BOOL            fRet;
  772.  
  773.     if (FAILED(OleGetClipboard(&pIDataObject)))
  774.         return FALSE;
  775.  
  776.     //CHAPTER13MOD
  777.     fRet=FQueryPasteFromData(pIDataObject);
  778.     //End CHAPTER13MOD
  779.  
  780.     pIDataObject->Release();
  781.     return fRet;
  782.     }
  783.  
  784.  
  785.  
  786. //CHAPTER13MOD
  787. /*
  788.  * CCosmoDoc::FQueryPasteFromData
  789.  * (Protected)
  790.  *
  791.  * Purpose:
  792.  *  Determines if we can paste data from a data object.
  793.  *
  794.  * Parameters:
  795.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  796.  *
  797.  * Return Value:
  798.  *  BOOL            TRUE if data is available, FALSE otherwise.
  799.  */
  800.  
  801. BOOL CCosmoDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject)
  802.     {
  803.     FORMATETC       fe;
  804.  
  805.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  806.     return (NOERROR==pIDataObject->QueryGetData(&fe));
  807.     }
  808. //End CHAPTER13MOD
  809.  
  810.  
  811.  
  812.  
  813. /*
  814.  * CCosmoDoc::Paste
  815.  *
  816.  * Purpose:
  817.  *  Retrieves the private data format from the clipboard and sets it
  818.  *  to the current figure in the editor window.
  819.  *
  820.  *  Note that if this function is called, then the clipboard format
  821.  *  is available because the Paste menu item is only enabled if the
  822.  *  format is present.
  823.  *
  824.  * Parameters:
  825.  *  hWndFrame       HWND of the main window.
  826.  *
  827.  * Return Value:
  828.  *  BOOL            TRUE if successful, FALSE otherwise.
  829.  */
  830.  
  831. BOOL CCosmoDoc::Paste(HWND hWndFrame)
  832.     {
  833.     LPDATAOBJECT    pIDataObject;
  834.     BOOL            fRet;
  835.  
  836.     if (FAILED(OleGetClipboard(&pIDataObject)))
  837.         return FALSE;
  838.  
  839.     //CHAPTER13MOD
  840.     fRet=PasteFromData(pIDataObject);
  841.     //End CHAPTER13MOD
  842.  
  843.     pIDataObject->Release();
  844.     return TRUE;
  845.     }
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852. //CHAPTER13MOD
  853. /*
  854.  * CCosmoDoc::PasteFromData
  855.  * (Protected)
  856.  *
  857.  * Purpose:
  858.  *  Retrieves the private data format from a data object and sets
  859.  *  it to the current figure in the editor window.
  860.  *
  861.  * Parameters:
  862.  *  pIDataObject    LPDATAOBJECT from which to paste.
  863.  *
  864.  * Return Value:
  865.  *  BOOL            TRUE if successful, FALSE otherwise.
  866.  */
  867.  
  868. BOOL CCosmoDoc::PasteFromData(LPDATAOBJECT pIDataObject)
  869.     {
  870.     FORMATETC       fe;
  871.     STGMEDIUM       stm;
  872.     BOOL            fRet;
  873.  
  874.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  875.     fRet=SUCCEEDED(pIDataObject->GetData(&fe, &stm));
  876.  
  877.     if (!fRet || NULL==stm.hGlobal)
  878.         return FALSE;
  879.  
  880.     if (fRet && NULL!=stm.hGlobal)
  881.         {
  882.         m_pPL->QueryInterface(IID_IDataObject
  883.             , (PPVOID)&pIDataObject);
  884.         pIDataObject->SetData(&fe, &stm, TRUE);
  885.         pIDataObject->Release();
  886.  
  887.         FDirtySet(TRUE);
  888.         }
  889.  
  890.     return fRet;
  891.     }
  892.  
  893.  
  894.  
  895.  
  896. /*
  897.  * CCosmoDoc::TransferObjectCreate
  898.  * (Protected)
  899.  *
  900.  * Purpose:
  901.  *  Creates a DataTransferObject and stuffs the current Polyline
  902.  *  data into it, used for both clipboard and drag-drop operations.
  903.  *
  904.  * Parameters:
  905.  *  None
  906.  *
  907.  * Return Value:
  908.  *  LPDATAOBJECT    Pointer to the object created, NULL on failure
  909.  */
  910.  
  911. LPDATAOBJECT CCosmoDoc::TransferObjectCreate(void)
  912.     {
  913.     UINT            i;
  914.     HRESULT         hr;
  915.     STGMEDIUM       stm;
  916.     FORMATETC       fe;
  917.     LPDATAOBJECT    pIDataSrc;
  918.     LPDATAOBJECT    pIDataObject=NULL;
  919.     const UINT      cFormats=3;
  920.     static UINT     rgcf[3]={0, CF_METAFILEPICT, CF_BITMAP};
  921.     static DWORD    rgtm[3]={TYMED_HGLOBAL, TYMED_MFPICT
  922.                         , TYMED_GDI};
  923.  
  924.     hr=CoCreateInstance(CLSID_DataTransferObject, NULL
  925.         , CLSCTX_INPROC_SERVER, IID_IDataObject
  926.         , (PPVOID)&pIDataObject);
  927.  
  928.     if (FAILED(hr))
  929.         return NULL;
  930.  
  931.     rgcf[0]=m_cf;
  932.  
  933.     hr=m_pPL->QueryInterface(IID_IDataObject, (PPVOID)&pIDataSrc);
  934.  
  935.     if (FAILED(hr))
  936.         {
  937.         pIDataObject->Release();
  938.         return NULL;
  939.         }
  940.  
  941.     for (i=0; i < cFormats; i++)
  942.         {
  943.         //Copy private data first.
  944.         SETDefFormatEtc(fe, rgcf[i], rgtm[i]);
  945.  
  946.         if (SUCCEEDED(pIDataSrc->GetData(&fe, &stm)))
  947.             pIDataObject->SetData(&fe, &stm, TRUE);
  948.         }
  949.  
  950.     pIDataSrc->Release();
  951.     return pIDataObject;    //Caller now responsible
  952.     }
  953.  
  954.  
  955.  
  956.  
  957.  
  958. /*
  959.  * CCosmoDoc::DropSelectTargetWindow
  960.  * (Protected)
  961.  *
  962.  * Purpose:
  963.  *  Creates a thin inverted frame around a window that we use to
  964.  *  show the window as a drop target.  This is a toggle function:
  965.  *  it uses XOR to create the effect so it must be called twice
  966.  *  to leave the window as it was.
  967.  *
  968.  * Parameters:
  969.  *  None
  970.  *
  971.  * Return Value:
  972.  *  None
  973.  */
  974.  
  975. void CCosmoDoc::DropSelectTargetWindow(void)
  976.     {
  977.     HDC         hDC;
  978.     RECT        rc;
  979.     UINT        dd=3;
  980.     HWND        hWnd;
  981.  
  982.     m_pPL->Window(&hWnd);
  983.     hDC=GetWindowDC(hWnd);
  984.     GetClientRect(hWnd, &rc);
  985.  
  986.     //Frame this window with inverted pixels
  987.  
  988.     //Top
  989.     PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, dd, DSTINVERT);
  990.  
  991.     //Bottom
  992.     PatBlt(hDC, rc.left, rc.bottom-dd, rc.right-rc.left, dd
  993.         , DSTINVERT);
  994.  
  995.     //Left excluding regions already affected by top and bottom
  996.     PatBlt(hDC, rc.left, rc.top+dd, dd, rc.bottom-rc.top-(2*dd)
  997.         , DSTINVERT);
  998.  
  999.     //Right excluding regions already affected by top and bottom
  1000.     PatBlt(hDC, rc.right-dd, rc.top+dd, dd, rc.bottom-rc.top-(2*dd)
  1001.         , DSTINVERT);
  1002.  
  1003.     ReleaseDC(hWnd, hDC);
  1004.     return;
  1005.     }
  1006.  
  1007. //End CHAPTER13MOD
  1008.  
  1009.  
  1010.  
  1011.  
  1012. /*
  1013.  * CCosmoDoc::ColorSet
  1014.  *
  1015.  * Purpose:
  1016.  *  Changes a color used in our contained Polyline.
  1017.  *
  1018.  * Parameters:
  1019.  *  iColor          UINT index of the color to change.
  1020.  *  cr              COLORREF new color.
  1021.  *
  1022.  * Return Value:
  1023.  *  COLORREF        Previous color for the given index.
  1024.  */
  1025.  
  1026. COLORREF CCosmoDoc::ColorSet(UINT iColor, COLORREF cr)
  1027.     {
  1028.     COLORREF    crRet;
  1029.  
  1030.     m_pPL->ColorSet(iColor, cr, &crRet);
  1031.     return crRet;
  1032.     }
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038. /*
  1039.  * CCosmoDoc::ColorGet
  1040.  *
  1041.  * Purpose:
  1042.  *  Retrieves a color currently in use in the Polyline.
  1043.  *
  1044.  * Parameters:
  1045.  *  iColor          UINT index of the color to retrieve.
  1046.  *
  1047.  * Return Value:
  1048.  *  COLORREF        Current color for the given index.
  1049.  */
  1050.  
  1051. COLORREF CCosmoDoc::ColorGet(UINT iColor)
  1052.     {
  1053.     COLORREF    crRet;
  1054.  
  1055.     m_pPL->ColorGet(iColor, &crRet);
  1056.     return crRet;
  1057.     }
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064. /*
  1065.  * CCosmoDoc::LineStyleSet
  1066.  *
  1067.  * Purpose:
  1068.  *  Changes the line style currently used in the Polyline
  1069.  *
  1070.  * Parameters:
  1071.  *  iStyle          UINT index of the new line style to use.
  1072.  *
  1073.  * Return Value:
  1074.  *  UINT            Previous line style.
  1075.  */
  1076.  
  1077. UINT CCosmoDoc::LineStyleSet(UINT iStyle)
  1078.     {
  1079.     UINT    i;
  1080.  
  1081.     m_pPL->LineStyleSet(iStyle, &i);
  1082.     return i;
  1083.     }
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091. /*
  1092.  * CCosmoDoc::LineStyleGet
  1093.  *
  1094.  * Purpose:
  1095.  *  Retrieves the line style currently used in the Polyline
  1096.  *
  1097.  * Parameters:
  1098.  *  None
  1099.  *
  1100.  * Return Value:
  1101.  *  UINT            Current line style.
  1102.  */
  1103.  
  1104.  
  1105. UINT CCosmoDoc::LineStyleGet(void)
  1106.     {
  1107.     UINT    i=0;
  1108.  
  1109.     //m_pPL might not be valid yet.
  1110.     if (NULL!=m_pPL)
  1111.         m_pPL->LineStyleGet(&i);
  1112.  
  1113.     return i;
  1114.     }
  1115.