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 / polyline / polyline.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-22  |  26.3 KB  |  1,169 lines

  1. /*
  2.  * POLYLINE.CPP
  3.  * Polyline Component Chapter 23
  4.  *
  5.  * Implementation of the CPolyline class that we expose as a
  6.  * component object.
  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 "polyline.h"
  17.  
  18.  
  19. /*
  20.  * CPolyline:CPolyline
  21.  * CPolyline::~CPolyline
  22.  *
  23.  * Constructor Parameters:
  24.  *  pUnkOuter       LPUNKNOWN of the controlling unknown.
  25.  *  pfnDestroy      PFNDESTROYED to call when an object is
  26.  *                  destroyed.
  27.  *  hInst           HINSTANCE of the application we're in.
  28.  */
  29.  
  30. CPolyline::CPolyline(LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy
  31.     , HINSTANCE hInst)
  32.     {
  33.     m_hWnd=NULL;
  34.     m_hInst=hInst;
  35.  
  36.     m_cRef=0;
  37.     m_pUnkOuter=pUnkOuter;
  38.     m_pfnDestroy=pfnDestroy;
  39.     m_fDirty=FALSE;
  40.  
  41.     m_pImpIPolyline=NULL;
  42.     m_pImpIConnPtCont=NULL;
  43.  
  44.     m_pAdv=NULL;
  45.     m_pConnPt=NULL;
  46.  
  47.     m_pST  =NULL;
  48.     m_cf   =0;
  49.     m_clsID=CLSID_Polyline19;
  50.  
  51.     m_pIStorage=NULL;
  52.     m_pIStream =NULL;
  53.  
  54.     m_pImpIPersistStorage=NULL;
  55.     m_pImpIPersistStreamInit=NULL;
  56.  
  57.     m_pImpIDataObject   =NULL;
  58.     m_pIDataAdviseHolder=NULL;
  59.  
  60.     m_pDefIUnknown       =NULL;
  61.     m_pDefIDataObject    =NULL;
  62.     m_pDefIViewObject    =NULL;
  63.     m_pDefIPersistStorage=NULL;
  64.  
  65.     m_pIOleAdviseHolder =NULL;
  66.     m_pImpIOleObject    =NULL;
  67.     m_pIOleClientSite   =NULL;
  68.     m_pImpIViewObject   =NULL;
  69.     m_pIAdviseSink      =NULL;
  70.  
  71.     m_dwFrozenAspects   =0;
  72.     m_dwAdviseAspects   =0;
  73.     m_dwAdviseFlags     =0;
  74.  
  75.     m_pImpIRunnableObject=NULL;
  76.     m_hDlg=NULL;
  77.  
  78.     m_pImpIExternalConnection=NULL;
  79.     m_fLockContainer=FALSE;
  80.     m_dwRegROT=0L;
  81.  
  82.     //CHAPTER23MOD
  83.     m_pIOleIPSite=NULL;
  84.     m_pIOleIPFrame=NULL;
  85.     m_pIOleIPUIWindow=NULL;
  86.     m_pImpIOleIPObject=NULL;
  87.     m_pImpIOleIPActiveObject=NULL;
  88.     m_hMenuShared=NULL;
  89.     m_hOLEMenu=NULL;
  90.     m_pHW=NULL;
  91.     m_fAllowInPlace=TRUE;
  92.     m_fUIActive=FALSE;
  93.  
  94.     m_fContainerKnowsInsideOut=FALSE;
  95.     //End CHAPTER23MOD
  96.  
  97.     return;
  98.     }
  99.  
  100.  
  101. CPolyline::~CPolyline(void)
  102.     {
  103.     LPUNKNOWN       pIUnknown=this;
  104.  
  105.     if (NULL!=m_pUnkOuter)
  106.         pIUnknown=m_pUnkOuter;
  107.  
  108.     if (NULL!=m_pST)
  109.         delete m_pST;
  110.  
  111.     if (NULL!=m_hDlg)
  112.         DestroyWindow(m_hDlg);
  113.  
  114.     /*
  115.      * In aggregation, release cached pointers but
  116.      * AddRef the controlling unknown first.  The 
  117.      * extra reference count protects from reentrancy.
  118.      */
  119.  
  120.     m_cRef++;
  121.  
  122.     pIUnknown->AddRef();
  123.     pIUnknown->AddRef();
  124.     pIUnknown->AddRef();
  125.  
  126.     ReleaseInterface(m_pDefIViewObject);
  127.     ReleaseInterface(m_pDefIDataObject);
  128.     ReleaseInterface(m_pDefIPersistStorage);
  129.  
  130.     m_cRef--;
  131.  
  132.     //Cached pointer rules do not apply to IUnknown
  133.     ReleaseInterface(m_pDefIUnknown);
  134.  
  135.     ReleaseInterface(m_pIAdviseSink);
  136.     ReleaseInterface(m_pIOleClientSite);
  137.     ReleaseInterface(m_pIOleAdviseHolder);
  138.  
  139.     DeleteInterfaceImp(m_pImpIOleObject);
  140.     DeleteInterfaceImp(m_pImpIViewObject);
  141.     DeleteInterfaceImp(m_pImpIRunnableObject);
  142.  
  143.     //CHAPTER23MOD
  144.     //Other in-place interfaces released in deactivation.
  145.     DeleteInterfaceImp(m_pImpIOleIPObject);
  146.     DeleteInterfaceImp(m_pImpIOleIPActiveObject);
  147.     //End CHAPTER23MOD
  148.  
  149.  
  150.     //Anything we might have registered in IRunnableObject::Run
  151.     INOLE_RevokeAsRunning(&m_dwRegROT);
  152.  
  153.     DeleteInterfaceImp(m_pImpIExternalConnection);
  154.     ReleaseInterface(m_pIDataAdviseHolder);
  155.     DeleteInterfaceImp(m_pImpIDataObject);
  156.  
  157.     DeleteInterfaceImp(m_pImpIPersistStreamInit);
  158.     DeleteInterfaceImp(m_pImpIPersistStorage);
  159.     ReleaseInterface(m_pIStream);
  160.     ReleaseInterface(m_pIStorage);
  161.  
  162.     DeleteInterfaceImp(m_pImpIConnPtCont);
  163.     DeleteInterfaceImp(m_pImpIPolyline);
  164.  
  165.     ReleaseInterface(m_pAdv);
  166.     ReleaseInterface(m_pConnPt);
  167.  
  168.     return;
  169.     }
  170.  
  171.  
  172.  
  173.  
  174. /*
  175.  * CPolyline::Init
  176.  *
  177.  * Purpose:
  178.  *  Performs any intiailization of a CPolyline that's prone to
  179.  *  failure that we also use internally before exposing the
  180.  *  object outside this DLL.
  181.  *
  182.  * Parameters:
  183.  *  None
  184.  *
  185.  * Return Value:
  186.  *  BOOL            TRUE if the function is successful,
  187.  *                  FALSE otherwise.
  188.  */
  189.  
  190. BOOL CPolyline::Init(void)
  191.     {
  192.     LPUNKNOWN       pIUnknown=this;
  193.     HRESULT         hr;
  194.  
  195.     if (NULL!=m_pUnkOuter)
  196.         pIUnknown=m_pUnkOuter;
  197.  
  198.     m_pST=new CStringTable(m_hInst);
  199.  
  200.     if (!m_pST->Init(IDS_POLYLINEMIN, IDS_POLYLINEMAX))
  201.         return FALSE;
  202.  
  203.     m_cf=RegisterClipboardFormat(SZPOLYLINECLIPFORMAT);
  204.  
  205.     m_pImpIPersistStorage=new CImpIPersistStorage(this, pIUnknown);
  206.  
  207.     if (NULL==m_pImpIPersistStorage)
  208.         return FALSE;
  209.  
  210.     m_pImpIPersistStreamInit=new CImpIPersistStreamInit(this
  211.         , pIUnknown);
  212.  
  213.     if (NULL==m_pImpIPersistStreamInit)
  214.         return FALSE;
  215.  
  216.     m_pImpIPolyline=new CImpIPolyline(this, pIUnknown);
  217.  
  218.     if (NULL==m_pImpIPolyline)
  219.         return FALSE;
  220.  
  221.     m_pImpIConnPtCont=new CImpIConnPtCont(this, pIUnknown);
  222.  
  223.     if (NULL==m_pImpIConnPtCont)
  224.         return FALSE;
  225.  
  226.     m_pConnPt=new CConnectionPoint(this);
  227.  
  228.     if (NULL==m_pConnPt)
  229.         return FALSE;
  230.  
  231.     m_pConnPt->AddRef();    //Reversed in destructor
  232.  
  233.     m_pImpIDataObject=new CImpIDataObject(this, pIUnknown);
  234.  
  235.     if (NULL==m_pImpIDataObject)
  236.         return FALSE;
  237.  
  238.     m_pImpIOleObject=new CImpIOleObject(this, pIUnknown);
  239.  
  240.     if (NULL==m_pImpIOleObject)
  241.         return FALSE;
  242.  
  243.     m_pImpIViewObject=new CImpIViewObject(this, pIUnknown);
  244.  
  245.     if (NULL==m_pImpIViewObject)
  246.         return FALSE;
  247.  
  248.     m_pImpIRunnableObject=new CImpIRunnableObject(this, pIUnknown);
  249.  
  250.     if (NULL==m_pImpIRunnableObject)
  251.         return FALSE;
  252.  
  253.     m_pImpIExternalConnection=new CImpIExternalConnection(this
  254.         , pIUnknown);
  255.  
  256.     if (NULL==m_pImpIExternalConnection)
  257.         return FALSE;
  258.  
  259.     //CHAPTER23MOD
  260.     m_pImpIOleIPObject=new CImpIOleInPlaceObject(this, pIUnknown);
  261.  
  262.     if (NULL==m_pImpIOleIPObject)
  263.         return FALSE;
  264.  
  265.     m_pImpIOleIPActiveObject=new CImpIOleInPlaceActiveObject(this
  266.         , pIUnknown);
  267.  
  268.     if (NULL==m_pImpIOleIPActiveObject)
  269.         return FALSE;
  270.     //End CHAPTER23MOD
  271.  
  272.     /*
  273.      * We're sitting at ref count 0 and the next call will AddRef a
  274.      * few times and Release a few times.  This insures we don't
  275.      * delete ourselves prematurely.
  276.      */
  277.     m_cRef++;
  278.  
  279.     //Aggregate OLE's cache for IOleCache* interfaces.
  280.     hr=CreateDataCache(pIUnknown, CLSID_Polyline19
  281.         , IID_IUnknown, (PPVOID)&m_pDefIUnknown);
  282.  
  283.     if (FAILED(hr))
  284.         return FALSE;
  285.  
  286.     /*
  287.      * NOTE:  The spec specifically states that any interfaces
  288.      * besides IUnknown that we obtain on an aggregated object
  289.      * should be Released immediately after we QueryInterface for
  290.      * them because the QueryInterface will AddRef us, and since
  291.      * we would not release these interfaces until we were
  292.      * destroyed, we'd never go away because we'd never get a zero
  293.      * ref count.
  294.      */
  295.  
  296.     //Now try to get other interfaces to which we delegate
  297.     hr=m_pDefIUnknown->QueryInterface(IID_IViewObject2
  298.         , (PPVOID)&m_pDefIViewObject);
  299.  
  300.     if (FAILED(hr))
  301.         return FALSE;
  302.  
  303.     pIUnknown->Release();
  304.  
  305.     hr=m_pDefIUnknown->QueryInterface(IID_IDataObject
  306.         , (PPVOID)&m_pDefIDataObject);
  307.  
  308.     if (FAILED(hr))
  309.         return FALSE;
  310.  
  311.     pIUnknown->Release();
  312.  
  313.     hr=m_pDefIUnknown->QueryInterface(IID_IPersistStorage
  314.         , (PPVOID)&m_pDefIPersistStorage);
  315.  
  316.     if (FAILED(hr))
  317.         return FALSE;
  318.  
  319.     pIUnknown->Release();
  320.  
  321.     m_cRef--;
  322.     m_pImpIPolyline->New();
  323.  
  324.     return TRUE;
  325.     }
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333. /*
  334.  * CPolyline::QueryInterface
  335.  * CPolyline::AddRef
  336.  * CPolyline::Release
  337.  *
  338.  * Purpose:
  339.  *  IUnknown members for CPolyline object.
  340.  */
  341.  
  342. STDMETHODIMP CPolyline::QueryInterface(REFIID riid, PPVOID ppv)
  343.     {
  344.     *ppv=NULL;
  345.  
  346.     if (IID_IUnknown==riid)
  347.         *ppv=this;
  348.  
  349.     if (IID_IConnectionPointContainer==riid)
  350.         *ppv=m_pImpIConnPtCont;
  351.  
  352.     if (IID_IPolyline10==riid)
  353.         *ppv=m_pImpIPolyline;
  354.  
  355.     if (IID_IPersistStorage==riid)
  356.         *ppv=m_pImpIPersistStorage;
  357.  
  358.     if (IID_IPersist==riid || IID_IPersistStream==riid
  359.         || IID_IPersistStreamInit==riid)
  360.         *ppv=m_pImpIPersistStreamInit;
  361.  
  362.     if (IID_IDataObject==riid)
  363.         *ppv=m_pImpIDataObject;
  364.  
  365.     if (IID_IOleObject==riid)
  366.         *ppv=m_pImpIOleObject;
  367.  
  368.     if (IID_IViewObject==riid || IID_IViewObject2==riid)
  369.         *ppv=m_pImpIViewObject;
  370.  
  371.     if (IID_IRunnableObject==riid)
  372.         *ppv=m_pImpIRunnableObject;
  373.  
  374.     if (IID_IExternalConnection==riid)
  375.         *ppv=m_pImpIExternalConnection;
  376.  
  377.     //CHAPTER23MOD
  378.     //IOleWindow will be the InPlaceObject
  379.     if (IID_IOleWindow==riid || IID_IOleInPlaceObject==riid)
  380.         *ppv=m_pImpIOleIPObject;
  381.     //End CHAPTER23MOD
  382.  
  383.     //Use the default handler's cache.
  384.     if (IID_IOleCache==riid || IID_IOleCache2==riid)
  385.         return m_pDefIUnknown->QueryInterface(riid, ppv);
  386.  
  387.     if (NULL!=*ppv)
  388.         {
  389.         ((LPUNKNOWN)*ppv)->AddRef();
  390.         return NOERROR;
  391.         }
  392.  
  393.     return ResultFromScode(E_NOINTERFACE);
  394.     }
  395.  
  396.  
  397. STDMETHODIMP_(ULONG) CPolyline::AddRef(void)
  398.     {
  399.     return ++m_cRef;
  400.     }
  401.  
  402.  
  403. STDMETHODIMP_(ULONG) CPolyline::Release(void)
  404.     {
  405.     if (0L!=--m_cRef)
  406.         return m_cRef;
  407.  
  408.     if (NULL!=m_pfnDestroy)
  409.         (*m_pfnDestroy)();
  410.  
  411.     delete this;
  412.     return 0L;
  413.     }
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421. /*
  422.  * CPolyline::RectConvertMappings
  423.  *
  424.  * Purpose:
  425.  *  Converts the contents of a rectangle from device (MM_TEXT) or
  426.  *  HIMETRIC to the other.
  427.  *
  428.  * Parameters:
  429.  *  pRect           LPRECT containing the rectangle to convert.
  430.  *  fToDevice       BOOL TRUE to convert from HIMETRIC to device,
  431.  *                  FALSE to convert device to HIMETRIC.
  432.  *
  433.  * Return Value:
  434.  *  None
  435.  */
  436.  
  437. void CPolyline::RectConvertMappings(LPRECT pRect, BOOL fToDevice)
  438.     {
  439.     HDC      hDC;
  440.     int      iLpx, iLpy;
  441.  
  442.     if (NULL==pRect)
  443.         return;
  444.  
  445.     hDC=GetDC(NULL);
  446.     iLpx=GetDeviceCaps(hDC, LOGPIXELSX);
  447.     iLpy=GetDeviceCaps(hDC, LOGPIXELSY);
  448.     ReleaseDC(NULL, hDC);
  449.  
  450.     if (fToDevice)
  451.         {
  452.         pRect->left=MulDiv(iLpx, pRect->left, HIMETRIC_PER_INCH);
  453.         pRect->top =MulDiv(iLpy, pRect->top , HIMETRIC_PER_INCH);
  454.  
  455.         pRect->right =MulDiv(iLpx, pRect->right, HIMETRIC_PER_INCH);
  456.         pRect->bottom=MulDiv(iLpy, pRect->bottom,HIMETRIC_PER_INCH);
  457.         }
  458.     else
  459.         {
  460.         pRect->left=MulDiv(pRect->left, HIMETRIC_PER_INCH, iLpx);
  461.         pRect->top =MulDiv(pRect->top , HIMETRIC_PER_INCH, iLpy);
  462.  
  463.         pRect->right =MulDiv(pRect->right, HIMETRIC_PER_INCH, iLpx);
  464.         pRect->bottom=MulDiv(pRect->bottom,HIMETRIC_PER_INCH, iLpy);
  465.         }
  466.  
  467.     return;
  468.     }
  469.  
  470.  
  471.  
  472. /*
  473.  * CPolyline::DataSet
  474.  *
  475.  * Purpose:
  476.  *  Sets the current data in this Polyline to a given structure.
  477.  *
  478.  * Parameters:
  479.  *  pplIn           PPOLYLINEDATA to initialize to.
  480.  *  fSizeToData     BOOL indicating if we're to size to the data
  481.  *                  or scale it.
  482.  *  fNotify         BOOL indicating if we're to send an advise
  483.  *                  on this change.
  484.  *
  485.  * Return Value:
  486.  *  HRESULT         NOERROR if successful, otherwise a
  487.  *                  POLYLINE_E_ value.
  488.  */
  489.  
  490. STDMETHODIMP CPolyline::DataSet(PPOLYLINEDATA pplIn
  491.     , BOOL fSizeToData, BOOL fNotify)
  492.     {
  493.     RECT            rc;
  494.  
  495.     /*
  496.      * Copy the structure in pplIn and repaint to reflect the
  497.      * new point set.  Note that unlike the RectSet message, we
  498.      * do no scaling, assuming that the rect in the structure
  499.      * is appropriate for the data.
  500.      */
  501.  
  502.     if (NULL==pplIn)
  503.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  504.  
  505.     m_pl=*pplIn;
  506.     m_fDirty=TRUE;
  507.  
  508.     /*
  509.      * If we're scaling the window to fit the data, then use
  510.      * RectSet passing our current rectangle as the new one.
  511.      * That makes sure that the data won't change but that the
  512.      * window is resized.
  513.      */
  514.  
  515.     if (fSizeToData)
  516.         {
  517.         POINT       pt;
  518.  
  519.         /*
  520.          * Get our offset in the parent window so we can RectSet
  521.          * to the right place since RectSet expects rectangle in
  522.          * parent coordinates and we get it in client coordinates.
  523.          */
  524.         if (NULL!=m_hWnd)
  525.             {
  526.             GetWindowRect(m_hWnd, &rc);
  527.             pt.x=rc.left;
  528.             pt.y=rc.top;
  529.             ScreenToClient(GetParent(m_hWnd), &pt);
  530.             RECTSTORECT(m_pl.rc, rc);
  531.             OffsetRect(&rc, pt.x, pt.y);
  532.  
  533.             //This will also cause a repaint.
  534.             m_pImpIPolyline->RectSet(&rc, fNotify);
  535.             }
  536.         }
  537.     else
  538.         {
  539.         if (NULL!=m_hWnd)
  540.             {
  541.             //Make sure we're updated.
  542.             InvalidateRect(m_hWnd, NULL, TRUE);
  543.             UpdateWindow(m_hWnd);
  544.             }
  545.         }
  546.  
  547.     SendAdvise(OBJECTCODE_DATACHANGED);
  548.     return NOERROR;
  549.     }
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557. /*
  558.  * CPolyline::DataGet
  559.  *
  560.  * Purpose:
  561.  *  Retrieves the Polyline's current data.
  562.  *
  563.  * Parameters:
  564.  *  pplIn           PPOLYLINEDATA into which we copy the data.
  565.  *
  566.  * Return Value:
  567.  *  HRESULT         NOERROR if successful, otherwise a
  568.  *                  POLYLINE_E_ value.
  569.  */
  570.  
  571. STDMETHODIMP CPolyline::DataGet(PPOLYLINEDATA pplIn)
  572.     {
  573.     if (NULL==pplIn)
  574.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  575.  
  576.     *pplIn=m_pl;
  577.     return NOERROR;
  578.     }
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585. /*
  586.  * CPolyline::RenderNative
  587.  *
  588.  * Purpose:
  589.  *  Retrieves the Polyline's data in a global memory handle.
  590.  *
  591.  * Parameters:
  592.  *  phMem           HGLOBAL * in which to store the handle.
  593.  *
  594.  * Return Value:
  595.  *  HRESULT         NOERROR if successful, otherwise a
  596.  *                  POLYLINE_E_ value.
  597.  */
  598.  
  599. STDMETHODIMP CPolyline::RenderNative(HGLOBAL *phMem)
  600.     {
  601.     HGLOBAL         hMem;
  602.     PPOLYLINEDATA   ppl;
  603.     HRESULT         hr=ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  604.  
  605.     if (NULL==phMem)
  606.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  607.  
  608.     hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, CBPOLYLINEDATA);
  609.  
  610.     if (NULL!=hMem)
  611.         {
  612.         ppl=(PPOLYLINEDATA)GlobalLock(hMem);
  613.         hr=DataGet(ppl);
  614.  
  615.         GlobalUnlock(hMem);
  616.  
  617.         if (FAILED(hr))
  618.             {
  619.             GlobalFree(hMem);
  620.             hMem=NULL;
  621.             }
  622.         }
  623.  
  624.     *phMem=hMem;
  625.     return hr;
  626.     }
  627.  
  628.  
  629.  
  630.  
  631. /*
  632.  * CPolyline::RenderBitmap
  633.  *
  634.  * Purpose:
  635.  *  Creates a bitmap image of the current Polyline.
  636.  *
  637.  * Parameters:
  638.  *  phBmp           HBITMAP * in which to return the bitmap.
  639.  *
  640.  * Return Value:
  641.  *  HRESULT         NOERROR if successful, otherwise a
  642.  *                  POLYLINE_E_ value.
  643.  */
  644.  
  645. STDMETHODIMP CPolyline::RenderBitmap(HBITMAP *phBmp)
  646.     {
  647.     HDC             hDC;
  648.     HDC             hMemDC;
  649.     HBITMAP         hBmp;
  650.     RECT            rc;
  651.     HGDIOBJ         hObj;
  652.  
  653.     if (NULL==phBmp)
  654.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  655.  
  656.     //Render a bitmap the size of the current rectangle.
  657.     hDC=GetDC(m_hWnd);
  658.     hMemDC=CreateCompatibleDC(hDC);
  659.  
  660.     GetClientRect(m_hWnd, &rc);
  661.     hBmp=CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
  662.  
  663.     if (NULL!=hBmp)
  664.         {
  665.         //Draw the POLYLINEDATA into the bitmap.
  666.         hObj=SelectObject(hMemDC, hBmp);
  667.         Draw(hMemDC, FALSE, TRUE, &rc, NULL);
  668.         SelectObject(hMemDC, hObj);
  669.         }
  670.  
  671.     DeleteDC(hMemDC);
  672.     ReleaseDC(m_hWnd, hDC);
  673.  
  674.     *phBmp=hBmp;
  675.     return NOERROR;
  676.     }
  677.  
  678.  
  679.  
  680. //RenderMetafile not necessary--now part of RenderMetafilePict.
  681.  
  682.  
  683.  
  684. /*
  685.  * CPolyline::RenderMetafilePict
  686.  *
  687.  * Purpose:
  688.  *  Renders the current Polyline into a METAFILEPICT structure in
  689.  *  global memory.
  690.  *
  691.  * Parameters:
  692.  *  phMem           HGLOBAL * in which to return the
  693.  *                  METAFILEPICT.
  694.  *
  695.  * Return Value:
  696.  *  HRESULT         NOERROR if successful, otherwise a
  697.  *                  POLYLINE_E_ value.
  698.  */
  699.  
  700. STDMETHODIMP CPolyline::RenderMetafilePict(HGLOBAL *phMem)
  701.     {
  702.     HGLOBAL         hMem;
  703.     HMETAFILE       hMF;
  704.     LPMETAFILEPICT  pMF;
  705.     RECT            rc;
  706.     HDC             hDC;
  707.  
  708.     if (NULL==phMem)
  709.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  710.  
  711.     //Create a memory metafile and return its handle.
  712.     hDC=(HDC)CreateMetaFile(NULL);
  713.  
  714.     if (NULL==hDC)
  715.         return ResultFromScode(STG_E_MEDIUMFULL);
  716.  
  717.     SetMapMode(hDC, MM_ANISOTROPIC);
  718.     GetClientRect(m_hWnd, &rc);
  719.     SetWindowOrgEx(hDC, 0, 0, NULL);
  720.     SetWindowExtEx(hDC, rc.right, rc.bottom, NULL);
  721.  
  722.     Draw(hDC, TRUE, TRUE, &rc, NULL);
  723.     hMF=CloseMetaFile(hDC);
  724.  
  725.     if (NULL==hMF)
  726.         return ResultFromScode(STG_E_MEDIUMFULL);
  727.  
  728.     //Allocate the METAFILEPICT structure.
  729.     hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE
  730.         , sizeof(METAFILEPICT));
  731.  
  732.     if (NULL==hMem)
  733.         {
  734.         DeleteMetaFile(hMF);
  735.         return ResultFromScode(E_FAIL);
  736.         }
  737.  
  738.     /*
  739.      * Global lock only fails in PMODE if the selector is invalid
  740.      * (like it was discarded) or references a 0 length segment,
  741.      * neither of which can happen here.
  742.      */
  743.     pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  744.  
  745.     pMF->hMF=hMF;
  746.     pMF->mm=MM_ANISOTROPIC;
  747.  
  748.     //Insert the extents in MM_HIMETRIC units.
  749.     GetClientRect(m_hWnd, &rc);
  750.     RectConvertMappings(&rc, FALSE);
  751.     pMF->xExt=rc.right;
  752.     pMF->yExt=rc.bottom;
  753.  
  754.     GlobalUnlock(hMem);
  755.  
  756.     *phMem=hMem;
  757.     return NOERROR;
  758.     }
  759.  
  760.  
  761.  
  762. /*
  763.  * CPolyline::Instance
  764.  *
  765.  * Purpose:
  766.  *  Provides access to the module instance.
  767.  *
  768.  * Parameters:
  769.  *  None
  770.  *
  771.  * Return Value:
  772.  *  HINSTANCE       The instance handle of the module.
  773.  */
  774.  
  775. HINSTANCE CPolyline::Instance(void)
  776.     {
  777.     return m_hInst;
  778.     }
  779.  
  780.  
  781.  
  782. /*
  783.  * CPolyline::String
  784.  *
  785.  * Purpose:
  786.  *  Provides string lookup in the Polyline string table.
  787.  *
  788.  * Parameters:
  789.  *  uID             UINT of the string to return.
  790.  *
  791.  * Return Value:
  792.  *  LPTSTR          Pointer to the string.
  793.  */
  794.  
  795. LPTSTR CPolyline::String(UINT uID)
  796.     {
  797.     return PSZ(uID);
  798.     }
  799.  
  800.  
  801.  
  802.  
  803. /*
  804.  * CPolyline::SendAdvise
  805.  *
  806.  * Purpose:
  807.  *  Calls the appropriate IOleClientSite or IAdviseSink member
  808.  *  function for various events such as closure, renaming, etc.
  809.  *
  810.  * Parameters:
  811.  *  uCode           UINT OBJECTCODE_* identifying the notification.
  812.  *
  813.  * Return Value:
  814.  *  None
  815.  */
  816.  
  817. void CPolyline::SendAdvise(UINT uCode)
  818.     {
  819.     DWORD       dwAspect=DVASPECT_CONTENT | DVASPECT_THUMBNAIL;
  820.  
  821.     switch (uCode)
  822.         {
  823.         case OBJECTCODE_SAVED:
  824.             if (NULL!=m_pIOleAdviseHolder)
  825.                 m_pIOleAdviseHolder->SendOnSave();
  826.             break;
  827.  
  828.         case OBJECTCODE_CLOSED:
  829.             if (NULL!=m_pIOleAdviseHolder)
  830.                 m_pIOleAdviseHolder->SendOnClose();
  831.  
  832.             break;
  833.  
  834.         case OBJECTCODE_RENAMED:
  835.             //Call IOleAdviseHolder::SendOnRename (later)
  836.             break;
  837.  
  838.         case OBJECTCODE_SAVEOBJECT:
  839.             if (m_fDirty && NULL!=m_pIOleClientSite)
  840.                 m_pIOleClientSite->SaveObject();
  841.  
  842.             m_fDirty=FALSE;
  843.             break;
  844.  
  845.         case OBJECTCODE_DATACHANGED:
  846.             m_fDirty=TRUE;
  847.  
  848.             //No flags are necessary here.
  849.             if (NULL!=m_pIDataAdviseHolder)
  850.                 {
  851.                 m_pIDataAdviseHolder->SendOnDataChange
  852.                     (m_pImpIDataObject, 0, 0);
  853.                 }
  854.  
  855.             if (NULL!=m_pIAdviseSink
  856.                 & (dwAspect & m_dwAdviseAspects))
  857.                 {
  858.                 m_pIAdviseSink->OnViewChange(dwAspect
  859.                     & m_dwAdviseAspects, 0);
  860.                 }
  861.  
  862.             break;
  863.  
  864.         case OBJECTCODE_SHOWWINDOW:
  865.             if (NULL!=m_pIOleClientSite)
  866.                 m_pIOleClientSite->OnShowWindow(TRUE);
  867.  
  868.             break;
  869.  
  870.         case OBJECTCODE_HIDEWINDOW:
  871.             if (NULL!=m_pIOleClientSite)
  872.                 m_pIOleClientSite->OnShowWindow(FALSE);
  873.  
  874.             break;
  875.  
  876.         case OBJECTCODE_SHOWOBJECT:
  877.             if (NULL!=m_pIOleClientSite)
  878.                 m_pIOleClientSite->ShowObject();
  879.  
  880.             break;
  881.         }
  882.  
  883.     return;
  884.     }
  885.  
  886.  
  887.  
  888. //CHAPTER23MOD
  889.  
  890. /*
  891.  * CPolyline::InPlaceActivate
  892.  *
  893.  * Purpose:
  894.  *  Goes through all the steps of activating the Polyline as an
  895.  *  in-place object.
  896.  *
  897.  * Parameters:
  898.  *  pActiveSite     LPOLECLIENTSITE of the active site we show in.
  899.  *  fIncludeUI      BOOL controls whether we call UIActivate too.
  900.  *
  901.  * Return Value:
  902.  *  HRESULT         Whatever error code is appropriate.
  903.  */
  904.  
  905. HRESULT CPolyline::InPlaceActivate(LPOLECLIENTSITE pActiveSite
  906.     , BOOL fIncludeUI)
  907.     {
  908.     HRESULT                 hr;
  909.     HWND                    hWnd;
  910.     HWND                    hWndHW;
  911.     RECT                    rcPos;
  912.     RECT                    rcClip;
  913.     OLEINPLACEFRAMEINFO     frameInfo;
  914.  
  915.     if (NULL==pActiveSite)
  916.         return ResultFromScode(E_INVALIDARG);
  917.  
  918.     if (NULL!=m_pIOleIPSite)
  919.         {
  920.         if (fIncludeUI)
  921.             UIActivate();
  922.  
  923.         return NOERROR;
  924.         }
  925.  
  926.  
  927.     //1.  Initialization, obtaining interfaces, OnInPlaceActivate.
  928.     hr=pActiveSite->QueryInterface(IID_IOleInPlaceSite
  929.         , (PPVOID)&m_pIOleIPSite);
  930.  
  931.     if (FAILED(hr))
  932.         return hr;
  933.  
  934.     hr=m_pIOleIPSite->CanInPlaceActivate();
  935.  
  936.     if (NOERROR!=hr)
  937.         {
  938.         m_pIOleIPSite->Release();
  939.         m_pIOleIPSite=NULL;
  940.         return ResultFromScode(E_FAIL);
  941.         }
  942.  
  943.     m_pIOleIPSite->OnInPlaceActivate();
  944.  
  945.  
  946.     //2.  Get the window context and create a window.
  947.     m_pIOleIPSite->GetWindow(&hWnd);
  948.     frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
  949.  
  950.     m_pIOleIPSite->GetWindowContext(&m_pIOleIPFrame
  951.         , &m_pIOleIPUIWindow, &rcPos, &rcClip, &frameInfo);
  952.  
  953.  
  954.     /*
  955.      * Create the hatch window after we get a parent window.  We
  956.      * could not create the hatch window sooner because had nothing
  957.      * to use for the parent.
  958.      */
  959.     m_pHW=new CHatchWin(m_hInst);
  960.  
  961.     if (NULL==m_pHW)
  962.         {
  963.         InPlaceDeactivate();
  964.         return ResultFromScode(E_OUTOFMEMORY);
  965.         }
  966.  
  967.     if (!m_pHW->Init(hWnd, ID_HATCHWINDOW, NULL))
  968.         {
  969.         InPlaceDeactivate();
  970.         return ResultFromScode(E_OUTOFMEMORY);
  971.         }
  972.  
  973.  
  974.     //Make sure dialog is hidden
  975.     if (NULL!=m_hDlg)
  976.         {
  977.         ShowWindow(m_hDlg, SW_HIDE);
  978.         SendAdvise(OBJECTCODE_HIDEWINDOW);
  979.         }
  980.  
  981.     //Move the hatch window to the container window.
  982.     hWndHW=m_pHW->Window();
  983.     SetParent(hWndHW, hWnd);
  984.  
  985.     //Move the Polyline window from the hidden dialog to hatch window
  986.     m_pHW->HwndAssociateSet(m_hWnd);
  987.     m_pHW->ChildSet(m_hWnd);
  988.     m_pHW->RectsSet(&rcPos, &rcClip);   //Positions polyline
  989.  
  990.     ShowWindow(hWndHW, SW_SHOW);
  991.     SendAdvise(OBJECTCODE_SHOWOBJECT);
  992.  
  993.     //3, 4, 5.  Do UI things: active object, shared menu, tools
  994.     hr=NOERROR;
  995.  
  996.     if (fIncludeUI)
  997.         hr=UIActivate();
  998.  
  999.     /*
  1000.      * Since we don't have an Undo while in-place, tell the continer
  1001.      * to free it's undo state immediately.
  1002.      */
  1003.     m_pIOleIPSite->DiscardUndoState();
  1004.  
  1005.     return hr;
  1006.     }
  1007.  
  1008.  
  1009.  
  1010.  
  1011. /*
  1012.  * CPolyline::InPlaceDeactivate
  1013.  *
  1014.  * Purpose:
  1015.  *  Reverses all the activation steps from InPlaceActivate.
  1016.  *
  1017.  * Parameters:
  1018.  *  None
  1019.  *
  1020.  * Return Value:
  1021.  *  None
  1022.  */
  1023.  
  1024. void CPolyline::InPlaceDeactivate(void)
  1025.     {
  1026.     UIDeactivate();
  1027.  
  1028.     if (NULL!=m_pHW)
  1029.         {
  1030.         RECT        rc;
  1031.  
  1032.         ShowWindow(m_pHW->Window(), SW_HIDE);
  1033.  
  1034.         //Reposition the polyline window in the dialog box.
  1035.         SetParent(m_hWnd, m_hDlg);
  1036.         CalcPolyRectInDialog(m_hDlg, &rc);
  1037.  
  1038.         SetWindowPos(m_hWnd, NULL, rc.left, rc.top
  1039.             , rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
  1040.  
  1041.         m_pHW->ChildSet(NULL);
  1042.  
  1043.         delete m_pHW;
  1044.         m_pHW=NULL;
  1045.         }
  1046.  
  1047.     ReleaseInterface(m_pIOleIPFrame);
  1048.     ReleaseInterface(m_pIOleIPUIWindow)
  1049.  
  1050.     if (NULL!=m_pIOleIPSite)
  1051.         {
  1052.         m_pIOleIPSite->OnInPlaceDeactivate();
  1053.         ReleaseInterface(m_pIOleIPSite);
  1054.         }
  1055.  
  1056.     return;
  1057.     }
  1058.  
  1059.  
  1060.  
  1061. /*
  1062.  * CPolyline::UIActivate
  1063.  *
  1064.  * Purpose:
  1065.  *  Goes through all the steps of activating the user interface of
  1066.  *  Polyline as an in-place object.
  1067.  *
  1068.  * Parameters:
  1069.  *  None
  1070.  *
  1071.  * Return Value:
  1072.  *  HRESULT         NOERROR or error code.
  1073.  */
  1074.  
  1075. HRESULT CPolyline::UIActivate(void)
  1076.     {
  1077.     //1.  Call IOleInPlaceSite::UIActivate
  1078.     if (NULL!=m_pIOleIPSite)
  1079.         m_pIOleIPSite->OnUIActivate();
  1080.  
  1081.     //2.  Set the active object
  1082.    #ifdef WIN32ANSI
  1083.     OLECHAR     szTemp[40];
  1084.  
  1085.     MultiByteToWideChar(CP_ACP, 0, PSZ(IDS_USERTYPE)
  1086.         , -1, szTemp, 40);
  1087.    #endif
  1088.  
  1089.     if (NULL!=m_pIOleIPFrame)
  1090.         {
  1091.         m_pIOleIPFrame->SetActiveObject(m_pImpIOleIPActiveObject
  1092.            #ifdef WIN32ANSI
  1093.             , szTemp);
  1094.            #else
  1095.             , PSZ(IDS_USERTYPE));
  1096.            #endif
  1097.         }
  1098.  
  1099.     if (NULL!=m_pIOleIPUIWindow)
  1100.         {
  1101.         m_pIOleIPUIWindow->SetActiveObject(m_pImpIOleIPActiveObject
  1102.            #ifdef WIN32ANSI
  1103.             , szTemp);
  1104.            #else
  1105.             , PSZ(IDS_USERTYPE));
  1106.            #endif
  1107.         }
  1108.  
  1109.     //3.  Critical for accelerators to work initially.
  1110.     SetFocus(m_pHW->Window());
  1111.  
  1112.     //4.  Negotiate border space.  Polyline doesn't need any.
  1113.     if (NULL!=m_pIOleIPFrame)
  1114.         m_pIOleIPFrame->SetBorderSpace(NULL);
  1115.  
  1116.     if (NULL!=m_pIOleIPUIWindow)
  1117.         m_pIOleIPUIWindow->SetBorderSpace(NULL);
  1118.  
  1119.  
  1120.     /*
  1121.      * 5.  Create the shared menu.  We don't have any, so tell
  1122.      *     the container to use its own menu.
  1123.      */
  1124.  
  1125.     if (NULL!=m_pIOleIPFrame)
  1126.         m_pIOleIPFrame->SetMenu(NULL, NULL, m_hWnd);
  1127.  
  1128.     m_fUIActive=TRUE;
  1129.     return NOERROR;
  1130.     }
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136. /*
  1137.  * CPolyline::UIDeactivate
  1138.  *
  1139.  * Purpose:
  1140.  *  Reverses all the user interface activation steps from
  1141.  *  UIActivate.
  1142.  *
  1143.  * Parameters:
  1144.  *  None
  1145.  *
  1146.  * Return Value:
  1147.  *  None
  1148.  */
  1149.  
  1150. void CPolyline::UIDeactivate(void)
  1151.     {
  1152.     m_fUIActive=FALSE;
  1153.  
  1154.     //We don't have any shared menu or tools to clean up.
  1155.  
  1156.     //Clear out the active objects
  1157.     if (NULL!=m_pIOleIPFrame)
  1158.         m_pIOleIPFrame->SetActiveObject(NULL, NULL);
  1159.  
  1160.     if (NULL!=m_pIOleIPUIWindow)
  1161.         m_pIOleIPUIWindow->SetActiveObject(NULL, NULL);
  1162.  
  1163.     if (NULL!=m_pIOleIPSite)
  1164.         m_pIOleIPSite->OnUIDeactivate(FALSE);
  1165.  
  1166.     return;
  1167.     }
  1168. //End CHAPTER23MOD
  1169.