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 / chap23 / cosmo / document.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  33.4 KB  |  1,490 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Cosmo Chapter 23
  4.  *
  5.  * Implementation of the CCosmoDoc derivation of CDocument as
  6.  * well as an implementation of CPolylineAdviseSink.
  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 "cosmo.h"
  17.  
  18.  
  19. /*
  20.  * CCosmoDoc::CCosmoDoc
  21.  * CCosmoDoc::~CCosmoDoc
  22.  *
  23.  * Constructor Parameters:
  24.  *  hInst           HINSTANCE of the application.
  25.  *  pFR             PCFrame of the frame object.
  26.  *  pAdv            PCDocumentAdviseSink to notify on events
  27.  */
  28.  
  29. CCosmoDoc::CCosmoDoc(HINSTANCE hInst, PCFrame pFR
  30.     , PCDocumentAdviseSink pAdv)
  31.     : CDocument(hInst, pFR, pAdv)
  32.     {
  33.     m_pPL=NULL;
  34.     m_pPLAdv=NULL;
  35.     m_uPrevSize=SIZE_RESTORED;
  36.  
  37.     m_pDropTarget=NULL;
  38.     m_fDragSource=FALSE;
  39.  
  40.     m_cfEmbedSource=RegisterClipboardFormat(CFSTR_EMBEDSOURCE);
  41.     m_cfObjectDescriptor=RegisterClipboardFormat
  42.         (CFSTR_OBJECTDESCRIPTOR);
  43.  
  44.     m_pFigure=NULL;
  45.     m_pMoniker=NULL;
  46.     m_dwRegROT=0L;
  47.  
  48.     m_cfLinkSource=RegisterClipboardFormat(CFSTR_LINKSOURCE);
  49.     m_cfLinkSrcDescriptor=RegisterClipboardFormat
  50.         (CFSTR_LINKSRCDESCRIPTOR);
  51.  
  52.     return;
  53.     }
  54.  
  55.  
  56. CCosmoDoc::~CCosmoDoc(void)
  57.     {
  58.     //Make sure the object is saved
  59.     m_pFigure->SendAdvise(OBJECTCODE_SAVEOBJECT);
  60.     m_pFigure->SendAdvise(OBJECTCODE_HIDEWINDOW);
  61.     m_pFigure->SendAdvise(OBJECTCODE_CLOSED);
  62.  
  63.     //If the document is reg'd as running, revoke and free the moniker
  64.     INOLE_RevokeAsRunning(&m_dwRegROT);
  65.  
  66.     if (NULL!=m_pMoniker)
  67.         m_pMoniker->Release();
  68.  
  69.     if (NULL!=m_pFigure)
  70.         {
  71.         m_pFigure->AddRef();
  72.         CoDisconnectObject(m_pFigure, 0L);
  73.         m_pFigure->Release();   //Starts shutdown if necessary.
  74.         delete m_pFigure;
  75.         }
  76.  
  77.     //Clean up the allocations we did in Init
  78.     if (NULL!=m_pPL)
  79.         delete m_pPL;
  80.  
  81.     if (NULL!=m_pPLAdv)
  82.         delete m_pPLAdv;
  83.  
  84.     return;
  85.     }
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92. /*
  93.  * CCosmoDoc::Init
  94.  *
  95.  * Purpose:
  96.  *  Initializes an already created document window.  The client
  97.  *  actually creates the window for us, then passes that here for
  98.  *  further initialization.
  99.  *
  100.  * Parameters:
  101.  *  pDI             PDOCUMENTINIT containing initialization
  102.  *                  parameters.
  103.  *
  104.  * Return Value:
  105.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  106.  */
  107.  
  108. BOOL CCosmoDoc::Init(PDOCUMENTINIT pDI)
  109.     {
  110.     RECT        rc;
  111.  
  112.     //Change the stringtable range to our customization.
  113.     pDI->idsMin=IDS_DOCUMENTMIN;
  114.     pDI->idsMax=IDS_DOCUMENTMAX;
  115.  
  116.     //Do default initialization
  117.     if (!CDocument::Init(pDI))
  118.         return FALSE;
  119.  
  120.     //Add the Polyline stuff we need.
  121.     m_pPLAdv=new CPolylineAdviseSink(this);
  122.     m_pPL   =new CPolyline(m_hInst);
  123.  
  124.     //Attempt to create our contained Polyline.
  125.     GetClientRect(m_hWnd, &rc);
  126.     InflateRect(&rc, -8, -8);
  127.  
  128.     if (!m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  129.         , ID_POLYLINE, m_pPLAdv))
  130.         return FALSE;
  131.  
  132.     m_pDropTarget=new CDropTarget(this);
  133.  
  134.     if (NULL!=m_pDropTarget)
  135.         {
  136.         m_pDropTarget->AddRef();
  137.         CoLockObjectExternal(m_pDropTarget, TRUE, FALSE);
  138.         RegisterDragDrop(m_hWnd, m_pDropTarget);
  139.         }
  140.  
  141.     m_pFigure=new CFigure(ObjectDestroyed, this);
  142.  
  143.     if (NULL==m_pFigure)
  144.         return FALSE;
  145.  
  146.     //We created an object, so count it.
  147.     g_cObj++;
  148.  
  149.     if (!m_pFigure->Init())
  150.         return FALSE;
  151.  
  152.     return TRUE;
  153.     }
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161. /*
  162.  * CCosmoDoc::FMessageHook
  163.  *
  164.  * Purpose:
  165.  *  Processes WM_SIZE for the document so we can resize
  166.  *  the Polyline.
  167.  *
  168.  * Parameters:
  169.  *  <WndProc Parameters>
  170.  *  pLRes           LRESULT * in which to store the return
  171.  *                  value for the message.
  172.  *
  173.  * Return Value:
  174.  *  BOOL            TRUE to prevent further processing,
  175.  *                  FALSE otherwise.
  176.  */
  177.  
  178. BOOL CCosmoDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  179.     , LPARAM lParam, LRESULT *pLRes)
  180.     {
  181.     UINT        dx, dy;
  182.     RECT        rc;
  183.  
  184.     *pLRes=0;
  185.  
  186.     if (WM_SIZE==iMsg)
  187.         {
  188.         //Don't effect the Polyline size to or from minimized state.
  189.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  190.             {
  191.             //When we change size, resize any Polyline we hold.
  192.             dx=LOWORD(lParam);
  193.             dy=HIWORD(lParam);
  194.  
  195.             /*
  196.              * If we are getting WM_SIZE in response to a Polyline
  197.              * notification, then don't resize the Polyline window
  198.              * again.
  199.              */
  200.             if (!m_fNoSize && NULL!=m_pPL)
  201.                 {
  202.                 //Resize the polyline to fit the new client
  203.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  204.                 m_pPL->RectSet(&rc, FALSE);
  205.  
  206.                 /*
  207.                  * We consider sizing something that makes the file
  208.                  * dirty, but not until we've finished the create
  209.                  * process, which is why we set fNoDirty to FALSE
  210.                  * in WM_CREATE since we get a WM_SIZE on the first
  211.                  * creation.
  212.                  */
  213.                 if (!m_fNoDirty)
  214.                     FDirtySet(TRUE);
  215.  
  216.                 SetRect(&rc, 0, 0, dx, dy);
  217.  
  218.                 if (NULL!=m_pAdv)
  219.                     m_pAdv->OnSizeChange(this, &rc);
  220.  
  221.                 m_fNoDirty=FALSE;
  222.                 }
  223.             }
  224.  
  225.         m_uPrevSize=wParam;
  226.         }
  227.  
  228.     if (WM_LBUTTONDOWN==iMsg)
  229.         {
  230.         LPDROPSOURCE    pIDropSource;
  231.         LPDATAOBJECT    pIDataObject;
  232.         HRESULT         hr;
  233.         SCODE           sc;
  234.         DWORD           dwEffect;
  235.  
  236.         /*
  237.          * The document has an 8 pixel border around the polyline
  238.          * window where we'll see mouse clicks.  A left mouse button
  239.          * click here means the start of a drag-drop operation.
  240.          *
  241.          * Since this is a modal operation, this IDropSource
  242.          * is entirely local.
  243.          */
  244.  
  245.         pIDropSource=new CDropSource(this);
  246.  
  247.         if (NULL==pIDropSource)
  248.             return FALSE;
  249.  
  250.         pIDropSource->AddRef();
  251.         m_fDragSource=TRUE;
  252.  
  253.         //Go get the data and start the ball rolling.
  254.         pIDataObject=TransferObjectCreate(FALSE);
  255.  
  256.         if (NULL!=pIDataObject)
  257.             {
  258.             hr=DoDragDrop(pIDataObject, pIDropSource
  259.                 , DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK
  260.                 , &dwEffect);
  261.  
  262.             pIDataObject->Release();
  263.             sc=GetScode(hr);
  264.             }
  265.         else
  266.             sc=E_FAIL;
  267.  
  268.         /*
  269.          * When we return from DoDragDrop, either cancel or drop.
  270.          * First toss the IDropSource we have here, then bail out
  271.          * on cancel, and possibly clear our data on a move drop.
  272.          */
  273.  
  274.         pIDropSource->Release();
  275.  
  276.         /*
  277.          * If dropped on the same document (determined using
  278.          * this flag, then dwEffect will be DROPEFFECT_NONE (see
  279.          * IDropTarget::Drop in DROPTGT.CPP).  In any case,
  280.          * reset this since the operation is done.
  281.          */
  282.  
  283.         m_fDragSource=FALSE;
  284.  
  285.         if (DRAGDROP_S_DROP==sc && DROPEFFECT_MOVE==dwEffect)
  286.             {
  287.             m_pPL->New();
  288.             FDirtySet(TRUE);
  289.             }
  290.  
  291.         //On a canceled drop or a copy we don't do anything else
  292.         return TRUE;
  293.         }
  294.  
  295.     if (WM_DESTROY==iMsg)
  296.         {
  297.         /*
  298.          * We have to revoke the drop target here because the window
  299.          * will be destroyed and the property forcefully removed
  300.          * before we could do this in the destructor.
  301.          */
  302.         if (NULL!=m_pDropTarget)
  303.             {
  304.             RevokeDragDrop(m_hWnd);
  305.             CoLockObjectExternal(m_pDropTarget, FALSE, TRUE);
  306.             ReleaseInterface(m_pDropTarget);
  307.             }
  308.  
  309.         return FALSE;
  310.         }
  311.  
  312.  
  313.     /*
  314.      * We return FALSE even on WM_SIZE so we can let the default
  315.      * procedure handle maximized MDI child windows appropriately.
  316.      */
  317.     return FALSE;
  318.     }
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327. /*
  328.  * CCosmoDoc::Clear
  329.  *
  330.  * Purpose:
  331.  *  Sets all contents in the document back to defaults with
  332.  *  no filename.
  333.  *
  334.  * Paramters:
  335.  *  None
  336.  *
  337.  * Return Value:
  338.  *  None
  339.  */
  340.  
  341. void CCosmoDoc::Clear(void)
  342.     {
  343.     //Completely reset the polyline
  344.     m_pPL->New();
  345.  
  346.     CDocument::Clear();
  347.     m_lVer=0;
  348.     return;
  349.     }
  350.  
  351.  
  352.  
  353. /*
  354.  * CCosmoDoc::FDirtySet
  355.  *
  356.  * Purpose:
  357.  *  Sets or clears the document 'dirty' flag returning the previous
  358.  *  state of that same flag.  We override this in Cosmo server to
  359.  *  send the OnDataChange notification as necessary.
  360.  *
  361.  * Parameters:
  362.  *  fDirty          BOOL indicating the new contents of the dirty
  363.  *                  flag.
  364.  *
  365.  * Return Value:
  366.  *  BOOL            Previous value of the dirty flag.
  367.  */
  368.  
  369. BOOL CCosmoDoc::FDirtySet(BOOL fDirty)
  370.     {
  371.     BOOL        fRet;
  372.  
  373.     fRet=CDocument::FDirtySet(fDirty);
  374.     m_pFigure->SendAdvise(OBJECTCODE_DATACHANGED);
  375.  
  376.     return fRet;
  377.     }
  378.  
  379.  
  380.  
  381.  
  382. /*
  383.  * CCosmoDoc::FDirtyGet
  384.  *
  385.  * Purpose:
  386.  *  Override of the normal FDirtyGet such that we never return dirty
  387.  *  for an embedded object we're serving since updates constantly
  388.  *  happen and since the object will be saved on closure.  This then
  389.  *  prevents any message boxes asking the user to save.
  390.  *
  391.  * Parameters:
  392.  *  None
  393.  *
  394.  * Return Value:
  395.  *  BOOL            TRUE if the document is dirty, FALSE otherwise.
  396.  */
  397.  
  398. BOOL CCosmoDoc::FDirtyGet(void)
  399.     {
  400.     if (m_pFigure->FIsEmbedded())
  401.         return FALSE;
  402.  
  403.     return m_fDirty;
  404.     }
  405.  
  406.  
  407.  
  408. /*
  409.  * CCosmoDoc::Load
  410.  *
  411.  * Purpose:
  412.  *  Loads a given document without any user interface overwriting
  413.  *  the previous contents of the Polyline window.  We do this by
  414.  *  opening the file and telling the Polyline to load itself from
  415.  *  that file.
  416.  *
  417.  * Parameters:
  418.  *  fChangeFile     BOOL indicating if we're to update the window
  419.  *                  title and the filename from using this file.
  420.  *  pszFile         LPTSTR to the filename to load, NULL if the file
  421.  *                  is new and untitled.
  422.  *
  423.  * Return Value:
  424.  *  UINT            An error value from DOCERR_*
  425.  */
  426.  
  427. UINT CCosmoDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  428.     {
  429.     HRESULT         hr;
  430.     LPSTORAGE       pIStorage;
  431.  
  432.     if (NULL==pszFile)
  433.         {
  434.         //For a new untitled document, just rename ourselves.
  435.         Rename(NULL);
  436.         m_lVer=VERSIONCURRENT;
  437.         return DOCERR_NONE;
  438.         }
  439.  
  440.     /*
  441.      * If not a Compound File, open the file using STGM_CONVERT in
  442.      * transacted mode to see old files as a storage with one stream
  443.      * called "CONTENTS" (which is conveniently the name we use
  444.      * in the new files).  We must use STGM_TRANSACTED here or else
  445.      * the old file will be immediately converted on disk:  we only
  446.      * want a converted image in memory from which to read.  In
  447.      * addition, note that we need STGM_READWRITE as well since
  448.      * conversion is inherently a write operation.
  449.      */
  450.  
  451.     pIStorage=NULL;
  452.  
  453.     if (NOERROR!=StgIsStorageFile(pszFile))
  454.         {
  455.         hr=StgCreateDocfile(pszFile,STGM_TRANSACTED | STGM_READWRITE
  456.             | STGM_CONVERT | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  457.  
  458.         if (FAILED(hr))
  459.             {
  460.             //If denied write access, try to load the old way
  461.             if (STG_E_ACCESSDENIED==GetScode(hr))
  462.                 m_lVer=m_pPL->ReadFromFile(pszFile);
  463.             else
  464.                 return DOCERR_COULDNOTOPEN;
  465.             }
  466.         }
  467.     else
  468.         {
  469.         hr=StgOpenStorage(pszFile, NULL, STGM_DIRECT | STGM_READ
  470.             | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
  471.  
  472.         if (FAILED(hr))
  473.             return DOCERR_COULDNOTOPEN;
  474.         }
  475.  
  476.     if (NULL!=pIStorage)
  477.         {
  478.         m_lVer=m_pPL->ReadFromStorage(pIStorage);
  479.         pIStorage->Release();
  480.         }
  481.  
  482.     if (POLYLINE_E_READFAILURE==m_lVer)
  483.         return DOCERR_READFAILURE;
  484.  
  485.     if (POLYLINE_E_UNSUPPORTEDVERSION==m_lVer)
  486.         return DOCERR_UNSUPPORTEDVERSION;
  487.  
  488.     if (fChangeFile)
  489.         Rename(pszFile);
  490.  
  491.     //Importing a file makes things dirty
  492.     FDirtySet(!fChangeFile);
  493.  
  494.     return DOCERR_NONE;
  495.     }
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503. /*
  504.  * CCosmoDoc::Save
  505.  *
  506.  * Purpose:
  507.  *  Writes the file to a known filename, requiring that the user has
  508.  *  previously used FileOpen or FileSaveAs to provide a filename.
  509.  *
  510.  * Parameters:
  511.  *  uType           UINT indicating the type of file the user
  512.  *                  requested to save in the File Save As dialog.
  513.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  514.  *                  current name.
  515.  *
  516.  * Return Value:
  517.  *  UINT            An error value from DOCERR_*
  518.  */
  519.  
  520. UINT CCosmoDoc::Save(UINT uType, LPTSTR pszFile)
  521.     {
  522.     LONG        lVer, lRet;
  523.     UINT        uTemp;
  524.     BOOL        fRename=TRUE;
  525.     HRESULT     hr;
  526.     LPSTORAGE   pIStorage;
  527.     BOOL        fEmbedding;
  528.  
  529.     fEmbedding=m_pFigure->FIsEmbedded();
  530.  
  531.     if (NULL==pszFile)
  532.         {
  533.         fRename=FALSE;
  534.         pszFile=m_szFile;
  535.         }
  536.  
  537.     /*
  538.      * Type 1 is the current version, type 2 is version 1.0 of the
  539.      * Polyline so we use this to send the right version to
  540.      * CPolyline::WriteToFile/WriteToStorage.
  541.      */
  542.  
  543.     switch (uType)
  544.         {
  545.         case 0:         //From Save, use loaded version.
  546.             lVer=m_lVer;
  547.             break;
  548.  
  549.         case 1:
  550.             lVer=VERSIONCURRENT;
  551.             break;
  552.  
  553.         case 2:
  554.             lVer=MAKELONG(0, 1);    //1.0
  555.             break;
  556.  
  557.         default:
  558.             return DOCERR_UNSUPPORTEDVERSION;
  559.         }
  560.  
  561.     /*
  562.      * If the version the user wants to save is different from the
  563.      * version that we loaded and m_lVer is not zero (new doc),
  564.      * then inform the user of the version change and verify.
  565.      */
  566.  
  567.     //For embedding, this is Save Copy As, so don't ask about versions.
  568.     if (0!=m_lVer && m_lVer!=lVer && !fEmbedding)
  569.         {
  570.         TCHAR       szMsg[128];
  571.  
  572.         wsprintf(szMsg, PSZ(IDS_VERSIONCHANGE)
  573.             , (UINT)HIWORD(m_lVer), (UINT)LOWORD(m_lVer)
  574.             , (UINT)HIWORD(lVer), (UINT)LOWORD(lVer));
  575.  
  576.         uTemp=MessageBox(m_hWnd, szMsg, PSZ(IDS_DOCUMENTCAPTION)
  577.             , MB_YESNOCANCEL);
  578.  
  579.         if (IDCANCEL==uTemp)
  580.             return DOCERR_CANCELLED;
  581.  
  582.         //If the user won't upgrade, revert to loaded version.
  583.         if (IDNO==uTemp)
  584.             lVer=m_lVer;
  585.         }
  586.  
  587.     /*
  588.      * For 1.0 files, still use the old code.  For new files, use
  589.      * storages instead
  590.      */
  591.     if (lVer==MAKELONG(0, 1))
  592.         lRet=m_pPL->WriteToFile(pszFile, lVer);
  593.     else
  594.         {
  595.         hr=StgCreateDocfile(pszFile, STGM_DIRECT | STGM_READWRITE
  596.             | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  597.  
  598.         if (FAILED(hr))
  599.             return DOCERR_COULDNOTOPEN;
  600.  
  601.         //Mark this as one of our class
  602.         WriteClassStg(pIStorage, CLSID_CosmoFigure);
  603.  
  604.         //Write user-readable class information
  605.         WriteFmtUserTypeStg(pIStorage, m_cf
  606.             , PSZ(IDS_CLIPBOARDFORMAT));
  607.  
  608.         lRet=m_pPL->WriteToStorage(pIStorage, lVer);
  609.         pIStorage->Release();
  610.         }
  611.  
  612.     if (POLYLINE_E_NONE!=lRet)
  613.         return DOCERR_WRITEFAILURE;
  614.  
  615.     //Saving makes us clean, but this doesn't apply to embedding.
  616.     if (!fEmbedding)
  617.         FDirtySet(FALSE);
  618.  
  619.     //Update the known version of this document.
  620.     m_lVer=lVer;
  621.  
  622.     /*
  623.      * If we're embedding, this is Save Copy As, so no rename.
  624.      * Note that we also don't care about having been set to clean
  625.      * since we're always 'clean' as an embedded object from
  626.      * the user's perspective.
  627.      */
  628.     if (fRename && !fEmbedding)
  629.         Rename(pszFile);
  630.  
  631.     return DOCERR_NONE;
  632.     }
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639. /*
  640.  * CCosmoDoc::Rename
  641.  *
  642.  * Purpose:
  643.  *  Overrides the normal rename to manage a moniker for the open
  644.  *  file.  We maintain no moniker for untitled documents, and
  645.  *  therefore do not allow linking to such documents.
  646.  *
  647.  * Parameters:
  648.  *  pszFile         LPTSTR to the new filename.
  649.  *
  650.  * Return Value:
  651.  *  None
  652.  */
  653.  
  654. void CCosmoDoc::Rename(LPTSTR pszFile)
  655.     {
  656.     LPMONIKER   pmk;
  657.  
  658.     //We don't need to change the base class, just augment...
  659.     CDocument::Rename(pszFile);
  660.  
  661.     //Unregister the old moniker (m_dwRegROT set to zero).
  662.     INOLE_RevokeAsRunning(&m_dwRegROT);
  663.  
  664.     ReleaseInterface(m_pMoniker);
  665.  
  666.     if (NULL!=pszFile)
  667.         {
  668.         CreateFileMoniker(pszFile, &pmk);
  669.  
  670.         if (NULL!=pmk)
  671.             {
  672.             m_pMoniker=pmk;     //pmk AddRef'd in CreateFileMoniker
  673.             INOLE_RegisterAsRunning(m_pFigure, m_pMoniker
  674.                 , 0, &m_dwRegROT);
  675.  
  676.             m_pFigure->SendAdvise(OBJECTCODE_RENAMED);
  677.             }
  678.         }
  679.  
  680.     return;
  681.     }
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688. /*
  689.  * CCosmoDoc::Undo
  690.  *
  691.  * Purpose:
  692.  *  Reverses a previous action.
  693.  *
  694.  * Parameters:
  695.  *  None
  696.  *
  697.  * Return Value:
  698.  *  None
  699.  */
  700.  
  701. void CCosmoDoc::Undo(void)
  702.     {
  703.     //CHAPTER23MOD
  704.     //Give the in-place object a chance for DeactivateAndUndo.
  705.     if (m_pFigure->Undo())
  706.         return;
  707.     //End CHAPTER23MOD
  708.  
  709.     m_pPL->Undo();
  710.     return;
  711.     }
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718. /*
  719.  * CCosmoDoc::Clip
  720.  *
  721.  * Purpose:
  722.  *  Places a private format, a metafile, and a bitmap of the display
  723.  *  on the clipboard, optionally implementing Cut by deleting the
  724.  *  data in the current window after rendering.
  725.  *
  726.  * Parameters:
  727.  *  hWndFrame       HWND of the main window.
  728.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  729.  *
  730.  * Return Value:
  731.  *  BOOL            TRUE if successful, FALSE otherwise.
  732.  */
  733.  
  734. BOOL CCosmoDoc::Clip(HWND hWndFrame, BOOL fCut)
  735.     {
  736.     BOOL            fRet=TRUE;
  737.     LPDATAOBJECT    pIDataObject;
  738.  
  739.     pIDataObject=TransferObjectCreate(fCut);
  740.  
  741.     if (NULL==pIDataObject)
  742.         return FALSE;
  743.  
  744.     fRet=SUCCEEDED(OleSetClipboard(pIDataObject));
  745.     pIDataObject->Release();
  746.  
  747.     //Delete our current data if "cut" succeeded.
  748.     if (fRet && fCut)
  749.         {
  750.         m_pPL->New();
  751.         FDirtySet(TRUE);
  752.         }
  753.  
  754.  
  755.     return fRet;
  756.     }
  757.  
  758.  
  759.  
  760.  
  761.  
  762. /*
  763.  * CCosmoDoc::RenderFormat
  764.  *
  765.  * Purpose:
  766.  *  Renders a specific clipboard format into global memory.
  767.  *
  768.  * Parameters:
  769.  *  cf              UINT format to render.
  770.  *
  771.  * Return Value:
  772.  *  HGLOBAL         Global memory handle containing the data.
  773.  */
  774.  
  775. HGLOBAL CCosmoDoc::RenderFormat(UINT cf)
  776.     {
  777.     HGLOBAL     hMem;
  778.  
  779.     if (cf==m_cf)
  780.         {
  781.         m_pPL->DataGetMem(VERSIONCURRENT, &hMem);
  782.         return hMem;
  783.         }
  784.  
  785.     switch (cf)
  786.         {
  787.         case CF_METAFILEPICT:
  788.             return m_pPL->RenderMetafilePict();
  789.  
  790.         case CF_BITMAP:
  791.             return (HGLOBAL)m_pPL->RenderBitmap();
  792.         }
  793.  
  794.     return NULL;
  795.     }
  796.  
  797.  
  798.  
  799.  
  800. /*
  801.  * CCosmoDoc::RenderMedium
  802.  *
  803.  * Purpose:
  804.  *  Like RenderFormat, this function creates a specific data format
  805.  *  based on the cf parameter.  Unlike RenderFormat, we store the
  806.  *  result in a STGMEDIUM in case it has a medium other than
  807.  *  TYMED_HGLOBAL.  For conveniece we'll centralize all compound
  808.  *  document formats here, hGlobal or not.
  809.  *
  810.  * Parameters:
  811.  *  cf              UINT clipboard format of interest.
  812.  *  pSTM            LSTGMEDIUM to fill.  We only fill the union
  813.  *                  and tymed.
  814.  *
  815.  * Return Value:
  816.  *  BOOL            TRUE if we could render the format,
  817.  *                  FALSE otherwise.
  818.  */
  819.  
  820. BOOL CCosmoDoc::RenderMedium(UINT cf, LPSTGMEDIUM pSTM)
  821.     {
  822.     if (NULL==pSTM)
  823.         return FALSE;
  824.  
  825.     if (cf==m_cfEmbedSource)
  826.         {
  827.         /*
  828.          * Embed Source data is an IStorage containing the native
  829.          * data (same as Embedded Object).  Since our data is small,
  830.          * it makes the most sense to create an IStorage in memory
  831.          * and put transfer that instead of a disk-based IStorage.
  832.          */
  833.  
  834.         pSTM->pstg=INOLE_CreateStorageOnHGlobal(STGM_DIRECT
  835.             | STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
  836.  
  837.         if (NULL==pSTM->pstg)
  838.             return FALSE;
  839.  
  840.         //Now save the data to the storage.
  841.         WriteClassStg(pSTM->pstg, CLSID_CosmoFigure);
  842.         WriteFmtUserTypeStg(pSTM->pstg, m_cf
  843.             , PSZ(IDS_CLIPBOARDFORMAT));
  844.  
  845.         if (POLYLINE_E_NONE!=m_pPL->WriteToStorage(pSTM->pstg
  846.             , VERSIONCURRENT))
  847.             {
  848.             /*
  849.              * When someone releases the IStorage, STORAGE.DLL will
  850.              * release the ILockBytes which, having fDeleteOnRelease
  851.              * TRUE (second parameter) will release the memory.
  852.              * That's why we don't have STGM_DELETEONRELEASE on the
  853.              * IStorage.
  854.              */
  855.             pSTM->pstg->Release();
  856.             return FALSE;
  857.             }
  858.  
  859.         pSTM->tymed=TYMED_ISTORAGE;
  860.         return TRUE;
  861.         }
  862.  
  863.     /*
  864.      * CFSTR_OBJECTDESCRIPTOR and CFSTR_LINKSRCDESCRIPTOR are the
  865.      * same formats, but only copy link source if we have a moniker.
  866.      */
  867.     if (cf==m_cfLinkSrcDescriptor && NULL==m_pMoniker)
  868.         return FALSE;
  869.  
  870.     if (cf==m_cfObjectDescriptor || cf==m_cfLinkSrcDescriptor)
  871.         {
  872.         SIZEL   szl, szlT;
  873.         POINTL  ptl;
  874.         RECT    rc;
  875.         LPTSTR  psz=NULL;
  876.  
  877.         m_pPL->SizeGet(&rc);
  878.         SETSIZEL(szlT, rc.right, rc.bottom);
  879.         XformSizeInPixelsToHimetric(NULL, &szlT, &szl);
  880.  
  881.         SETPOINTL(ptl, 0, 0);
  882.  
  883.         //Include the moniker display name now, if we have one.
  884.         if (m_pMoniker)
  885.             {
  886.             LPBC    pbc;
  887.  
  888.             CreateBindCtx(0, &pbc);
  889.            #ifdef WIN32ANSI
  890.             LPOLESTR    pszW;
  891.  
  892.             m_pMoniker->GetDisplayName(pbc, NULL, &pszW);
  893.             psz=(LPTSTR)CoTaskMemAlloc(512);
  894.             WideCharToMultiByte(CP_ACP, 0, pszW, -1, psz, 512
  895.                 , NULL, NULL);
  896.             CoTaskMemFree((void *)pszW);
  897.            #else
  898.             m_pMoniker->GetDisplayName(pbc, NULL, &psz);
  899.            #endif
  900.             pbc->Release();
  901.             }
  902.  
  903.         pSTM->hGlobal=INOLE_AllocObjectDescriptor
  904.             (CLSID_CosmoFigure, DVASPECT_CONTENT, szl, ptl
  905.             , OLEMISC_RECOMPOSEONRESIZE, PSZ(IDS_OBJECTDESCRIPTION)
  906.             , psz);
  907.  
  908.         CoTaskMemFree((void *)psz);
  909.         pSTM->tymed=TYMED_HGLOBAL;
  910.         return (NULL!=pSTM->hGlobal);
  911.         }
  912.  
  913.     if (cf==m_cfLinkSource)
  914.         {
  915.         if (NULL!=m_pMoniker)
  916.             {
  917.             FORMATETC   fe;
  918.             HRESULT     hr;
  919.  
  920.             pSTM->tymed=TYMED_NULL;
  921.             SETDefFormatEtc(fe, cf, TYMED_ISTREAM);
  922.             hr=INOLE_GetLinkSourceData(m_pMoniker
  923.                 , (LPCLSID)&CLSID_CosmoFigure, &fe, pSTM);
  924.  
  925.             return SUCCEEDED(hr);
  926.             }
  927.         }
  928.  
  929.     return FALSE;
  930.     }
  931.  
  932.  
  933.  
  934.  
  935.  
  936. /*
  937.  * CCosmoDoc::FQueryPaste
  938.  *
  939.  * Purpose:
  940.  *  Determines if we can paste data from the clipboard.
  941.  *
  942.  * Parameters:
  943.  *  None
  944.  *
  945.  * Return Value:
  946.  *  BOOL            TRUE if data is available, FALSE otherwise.
  947.  */
  948.  
  949. BOOL CCosmoDoc::FQueryPaste(void)
  950.     {
  951.     LPDATAOBJECT    pIDataObject;
  952.     BOOL            fRet;
  953.  
  954.     if (FAILED(OleGetClipboard(&pIDataObject)))
  955.         return FALSE;
  956.  
  957.     fRet=FQueryPasteFromData(pIDataObject);
  958.     pIDataObject->Release();
  959.     return fRet;
  960.     }
  961.  
  962.  
  963.  
  964. /*
  965.  * CCosmoDoc::FQueryPasteFromData
  966.  * (Protected)
  967.  *
  968.  * Purpose:
  969.  *  Determines if we can paste data from a data object.
  970.  *
  971.  * Parameters:
  972.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  973.  *
  974.  * Return Value:
  975.  *  BOOL            TRUE if data is available, FALSE otherwise.
  976.  */
  977.  
  978. BOOL CCosmoDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject)
  979.     {
  980.     FORMATETC       fe;
  981.  
  982.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  983.     return (NOERROR==pIDataObject->QueryGetData(&fe));
  984.     }
  985.  
  986.  
  987.  
  988.  
  989. /*
  990.  * CCosmoDoc::Paste
  991.  *
  992.  * Purpose:
  993.  *  Retrieves the private data format from the clipboard and sets it
  994.  *  to the current figure in the editor window.
  995.  *
  996.  *  Note that if this function is called, then the clipboard format
  997.  *  is available because the Paste menu item is only enabled if the
  998.  *  format is present.
  999.  *
  1000.  * Parameters:
  1001.  *  hWndFrame       HWND of the main window.
  1002.  *
  1003.  * Return Value:
  1004.  *  BOOL            TRUE if successful, FALSE otherwise.
  1005.  */
  1006.  
  1007. BOOL CCosmoDoc::Paste(HWND hWndFrame)
  1008.     {
  1009.     LPDATAOBJECT    pIDataObject;
  1010.     BOOL            fRet;
  1011.  
  1012.     if (FAILED(OleGetClipboard(&pIDataObject)))
  1013.         return FALSE;
  1014.  
  1015.     fRet=PasteFromData(pIDataObject);
  1016.     pIDataObject->Release();
  1017.  
  1018.     return fRet;
  1019.     }
  1020.  
  1021.  
  1022.  
  1023.  
  1024. /*
  1025.  * CCosmoDoc::PasteFromData
  1026.  * (Protected)
  1027.  *
  1028.  * Purpose:
  1029.  *  Retrieves the private data format from a data object and sets
  1030.  *  it to the current figure in the editor window.
  1031.  *
  1032.  * Parameters:
  1033.  *  pIDataObject    LPDATAOBJECT from which to paste.
  1034.  *
  1035.  * Return Value:
  1036.  *  BOOL            TRUE if successful, FALSE otherwise.
  1037.  */
  1038.  
  1039. BOOL CCosmoDoc::PasteFromData(LPDATAOBJECT pIDataObject)
  1040.     {
  1041.     FORMATETC       fe;
  1042.     STGMEDIUM       stm;
  1043.     BOOL            fRet;
  1044.  
  1045.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  1046.     fRet=SUCCEEDED(pIDataObject->GetData(&fe, &stm));
  1047.  
  1048.     if (fRet && NULL!=stm.hGlobal)
  1049.         {
  1050.         m_pPL->DataSetMem(stm.hGlobal, FALSE, FALSE, TRUE);
  1051.         ReleaseStgMedium(&stm);
  1052.         FDirtySet(TRUE);
  1053.         }
  1054.  
  1055.     return fRet;
  1056.     }
  1057.  
  1058.  
  1059.  
  1060.  
  1061. /*
  1062.  * CCosmoDoc::TransferObjectCreate
  1063.  * (Protected)
  1064.  *
  1065.  * Purpose:
  1066.  *  Creates a DataTransferObject and stuffs the current Polyline
  1067.  *  data into it, used for both clipboard and drag-drop operations.
  1068.  *
  1069.  * Parameters:
  1070.  *  fCut            BOOL TRUE if we're cutting, FALSE if we're
  1071.  *                  copying.
  1072.  *
  1073.  * Return Value:
  1074.  *  LPDATAOBJECT    Pointer to the object created, NULL on failure
  1075.  */
  1076.  
  1077. LPDATAOBJECT CCosmoDoc::TransferObjectCreate(BOOL fCut)
  1078.     {
  1079.     UINT            i;
  1080.     HRESULT         hr;
  1081.     STGMEDIUM       stm;
  1082.     FORMATETC       fe;
  1083.     LPDATAOBJECT    pIDataObject=NULL;
  1084.     const UINT      cFormats=7;
  1085.     static UINT     rgcf[7]={0, 0, 0, CF_METAFILEPICT, CF_BITMAP, 0, 0};
  1086.     static DWORD    rgtm[7]={TYMED_HGLOBAL, TYMED_ISTORAGE, TYMED_HGLOBAL
  1087.         , TYMED_MFPICT, TYMED_GDI, TYMED_ISTREAM, TYMED_HGLOBAL};
  1088.  
  1089.     hr=CoCreateInstance(CLSID_DataTransferObject, NULL
  1090.         , CLSCTX_INPROC_SERVER, IID_IDataObject
  1091.         , (PPVOID)&pIDataObject);
  1092.  
  1093.     if (FAILED(hr))
  1094.         return NULL;
  1095.  
  1096.     rgcf[0]=m_cf;
  1097.     rgcf[1]=m_cfEmbedSource;
  1098.     rgcf[2]=m_cfObjectDescriptor;
  1099.  
  1100.     //Don't include link stuff for cutting (0 format always fails)
  1101.     if (!fCut)
  1102.         {
  1103.         rgcf[5]=m_cfLinkSource;
  1104.         rgcf[6]=m_cfLinkSrcDescriptor;
  1105.         }
  1106.  
  1107.     for (i=0; i < cFormats; i++)
  1108.         {
  1109.         /*
  1110.          * RenderFormat handles memory handles, but for compound doc
  1111.          * formats we need something more.  So if RenderFormat fails
  1112.          * (which it will for i=1, try our latest addition which
  1113.          * writes to a different field in the STGMEDIUM.
  1114.          */
  1115.         stm.hGlobal=RenderFormat(rgcf[i]);
  1116.  
  1117.         if (NULL==stm.hGlobal)
  1118.             {
  1119.             if (!RenderMedium(rgcf[i], &stm))
  1120.                 continue;
  1121.             }
  1122.  
  1123.         stm.tymed=rgtm[i];
  1124.         stm.pUnkForRelease=NULL;
  1125.         SETDefFormatEtc(fe, rgcf[i], rgtm[i]);
  1126.         pIDataObject->SetData(&fe, &stm, TRUE);
  1127.         }
  1128.  
  1129.     return pIDataObject;    //Caller now responsible
  1130.     }
  1131.  
  1132.  
  1133.  
  1134. /*
  1135.  * CCosmoDoc::DropSelectTargetWindow
  1136.  * (Protected)
  1137.  *
  1138.  * Purpose:
  1139.  *  Creates a thin inverted frame around a window that we use to
  1140.  *  show the window as a drop target.  This is a toggle function:
  1141.  *  It uses XOR to create the effect so it must be called twice to
  1142.  *  leave the window as it was.
  1143.  *
  1144.  * Parameters:
  1145.  *  None
  1146.  *
  1147.  * Return Value:
  1148.  *  None
  1149.  */
  1150.  
  1151. void CCosmoDoc::DropSelectTargetWindow(void)
  1152.     {
  1153.     HDC         hDC;
  1154.     RECT        rc;
  1155.     UINT        dd=3;
  1156.     HWND        hWnd;
  1157.  
  1158.     hWnd=m_pPL->Window();
  1159.     hDC=GetWindowDC(hWnd);
  1160.     GetClientRect(hWnd, &rc);
  1161.  
  1162.     //Frame this window with inverted pixels
  1163.  
  1164.     //Top
  1165.     PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, dd, DSTINVERT);
  1166.  
  1167.     //Bottom
  1168.     PatBlt(hDC, rc.left, rc.bottom-dd, rc.right-rc.left, dd
  1169.         , DSTINVERT);
  1170.  
  1171.     //Left excluding regions already affected by top and bottom
  1172.     PatBlt(hDC, rc.left, rc.top+dd, dd, rc.bottom-rc.top-(2*dd)
  1173.         , DSTINVERT);
  1174.  
  1175.     //Right excluding regions already affected by top and bottom
  1176.     PatBlt(hDC, rc.right-dd, rc.top+dd, dd, rc.bottom-rc.top-(2*dd)
  1177.         , DSTINVERT);
  1178.  
  1179.     ReleaseDC(hWnd, hDC);
  1180.     return;
  1181.     }
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187. //CHAPTER23MOD
  1188. /*
  1189.  * CCosmoDoc::OpenInPlaceObject
  1190.  *
  1191.  * Purpose:
  1192.  *  Instructs the current figure object to open into a window from
  1193.  *  in-place active state, if applicable.
  1194.  *
  1195.  * Parameters:
  1196.  *  None
  1197.  *
  1198.  * Return Value:
  1199.  *  None
  1200.  */
  1201.  
  1202. void CCosmoDoc::OpenInPlaceObject(void)
  1203.     {
  1204.     if (NULL!=m_pFigure)
  1205.         m_pFigure->OpenIntoWindow();
  1206.  
  1207.     return;
  1208.     }
  1209.  
  1210. //End CHAPTER23MOD
  1211.  
  1212.  
  1213.  
  1214.  
  1215. /*
  1216.  * CCosmoDoc::ColorSet
  1217.  *
  1218.  * Purpose:
  1219.  *  Changes a color used in our contained Polyline.
  1220.  *
  1221.  * Parameters:
  1222.  *  iColor          UINT index of the color to change.
  1223.  *  cr              COLORREF new color.
  1224.  *
  1225.  * Return Value:
  1226.  *  COLORREF        Previous color for the given index.
  1227.  */
  1228.  
  1229. COLORREF CCosmoDoc::ColorSet(UINT iColor, COLORREF cr)
  1230.     {
  1231.     return m_pPL->ColorSet(iColor, cr);
  1232.     }
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238. /*
  1239.  * CCosmoDoc::ColorGet
  1240.  *
  1241.  * Purpose:
  1242.  *  Retrieves a color currently in use in the Polyline.
  1243.  *
  1244.  * Parameters:
  1245.  *  iColor          UINT index of the color to retrieve.
  1246.  *
  1247.  * Return Value:
  1248.  *  COLORREF        Current color for the given index.
  1249.  */
  1250.  
  1251. COLORREF CCosmoDoc::ColorGet(UINT iColor)
  1252.     {
  1253.     return m_pPL->ColorGet(iColor);
  1254.     }
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261. /*
  1262.  * CCosmoDoc::LineStyleSet
  1263.  *
  1264.  * Purpose:
  1265.  *  Changes the line style currently used in the Polyline
  1266.  *
  1267.  * Parameters:
  1268.  *  iStyle          UINT index of the new line style to use.
  1269.  *
  1270.  * Return Value:
  1271.  *  UINT            Previous line style.
  1272.  */
  1273.  
  1274.  
  1275. UINT CCosmoDoc::LineStyleSet(UINT iStyle)
  1276.     {
  1277.     return m_pPL->LineStyleSet(iStyle);
  1278.     }
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286. /*
  1287.  * CCosmoDoc::LineStyleGet
  1288.  *
  1289.  * Purpose:
  1290.  *  Retrieves the line style currently used in the Polyline
  1291.  *
  1292.  * Parameters:
  1293.  *  None
  1294.  *
  1295.  * Return Value:
  1296.  *  UINT            Current line style.
  1297.  */
  1298.  
  1299.  
  1300. UINT CCosmoDoc::LineStyleGet(void)
  1301.     {
  1302.     if (NULL==m_pPL)    //m_pPL might not be valid yet
  1303.         return 0L;
  1304.  
  1305.     return m_pPL->LineStyleGet();
  1306.     }
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315. /*
  1316.  * CPolylineAdviseSink::CPolylineAdviseSink
  1317.  * CPolylineAdviseSink::~CPolylineAdviseSink
  1318.  *
  1319.  * Constructor Parameters:
  1320.  *  pv              LPVOID to store in this object
  1321.  */
  1322.  
  1323. CPolylineAdviseSink::CPolylineAdviseSink(LPVOID pv)
  1324.     {
  1325.     m_pv=pv;
  1326.     return;
  1327.     }
  1328.  
  1329.  
  1330. CPolylineAdviseSink::~CPolylineAdviseSink(void)
  1331.     {
  1332.     return;
  1333.     }
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339. /*
  1340.  * CPolylineAdviseSink::OnPointChange
  1341.  *
  1342.  * Purpose:
  1343.  *  Informs the document that the polyline added or removed a point.
  1344.  *
  1345.  * Parameters:
  1346.  *  None
  1347.  *
  1348.  * Return Value:
  1349.  *  None
  1350.  */
  1351.  
  1352. void CPolylineAdviseSink::OnPointChange(void)
  1353.     {
  1354.     PCDocument      pDoc=(PCDocument)m_pv;
  1355.  
  1356.     pDoc->FDirtySet(TRUE);
  1357.     return;
  1358.     }
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365. /*
  1366.  * CPolylineAdviseSink::OnSizeChange
  1367.  *
  1368.  * Purpose:
  1369.  *  Informs the document that the polyline changed size.
  1370.  *
  1371.  * Parameters:
  1372.  *  None
  1373.  *
  1374.  * Return Value:
  1375.  *  None
  1376.  */
  1377.  
  1378. void CPolylineAdviseSink::OnSizeChange(void)
  1379.     {
  1380.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  1381.     RECT            rc;
  1382.     DWORD           dwStyle;
  1383.  
  1384.     /*
  1385.      * Polyline window is informing us that it changed size in
  1386.      * response to setting it's data.  Therefore we have to
  1387.      * size ourselves accordingly but without moving the screen
  1388.      * position of the polyline window.
  1389.      */
  1390.  
  1391.     pDoc->m_fNoSize=TRUE;
  1392.  
  1393.     //Set the document window size.
  1394.     GetWindowRect(pDoc->m_pPL->Window(), &rc);
  1395.     InflateRect(&rc, 8, 8);
  1396.  
  1397.     //Adjust for a window sans menu
  1398.     dwStyle=GetWindowLong(pDoc->m_hWnd, GWL_STYLE);
  1399.     AdjustWindowRect(&rc, dwStyle, FALSE);
  1400.  
  1401.     SetWindowPos(pDoc->m_hWnd, NULL, 0, 0, rc.right-rc.left
  1402.         , rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER);
  1403.  
  1404.     if (NULL!=pDoc->m_pAdv)
  1405.         pDoc->m_pAdv->OnSizeChange(pDoc, &rc);
  1406.  
  1407.     pDoc->m_fNoSize=FALSE;
  1408.     pDoc->FDirtySet(TRUE);
  1409.  
  1410.     return;
  1411.     }
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417. /*
  1418.  * CPolylineAdviseSink::OnDataChange
  1419.  *
  1420.  * Purpose:
  1421.  *  Informs the document that the polyline data changed.
  1422.  *
  1423.  * Parameters:
  1424.  *  None
  1425.  *
  1426.  * Return Value:
  1427.  *  None
  1428.  */
  1429.  
  1430. void CPolylineAdviseSink::OnDataChange(void)
  1431.     {
  1432.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  1433.  
  1434.     if (NULL!=pDoc->m_pAdv)
  1435.         pDoc->m_pAdv->OnDataChange(pDoc);
  1436.  
  1437.     pDoc->FDirtySet(TRUE);
  1438.     return;
  1439.     }
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445. /*
  1446.  * CPolylineAdviseSink::OnColorChange
  1447.  *
  1448.  * Purpose:
  1449.  *  Informs the document that the polyline data changed a color.
  1450.  *
  1451.  * Parameters:
  1452.  *  None
  1453.  *
  1454.  * Return Value:
  1455.  *  None
  1456.  */
  1457.  
  1458. void CPolylineAdviseSink::OnColorChange(void)
  1459.     {
  1460.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  1461.  
  1462.     pDoc->FDirtySet(TRUE);
  1463.     return;
  1464.     }
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470. /*
  1471.  * CPolylineAdviseSink::OnLineStyleChange
  1472.  *
  1473.  * Purpose:
  1474.  *  Informs the document that the polyline changed its line style.
  1475.  *
  1476.  * Parameters:
  1477.  *  None
  1478.  *
  1479.  * Return Value:
  1480.  *  None
  1481.  */
  1482.  
  1483. void CPolylineAdviseSink::OnLineStyleChange(void)
  1484.     {
  1485.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  1486.  
  1487.     pDoc->FDirtySet(TRUE);
  1488.     return;
  1489.     }
  1490.