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 / cosmo / document.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  25KB  |  1,162 lines

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