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 / chap08 / polyline / ipolylin.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  21KB  |  946 lines

  1. /*
  2.  * IPOLYLIN.CPP
  3.  * Polyline Component Chapter 8
  4.  *
  5.  * Implementation of the IPolyline8 interface that we expose on the
  6.  * CPolyline 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.  * CImpIPolyline:CImpIPolyline
  21.  * CImpIPolyline::~CImpIPolyline
  22.  *
  23.  * Constructor Parameters:
  24.  *  pObj            PCPolyline pointing to the object we live in.
  25.  *  pUnkOuter       LPUNKNOWN of the controlling unknown.
  26.  */
  27.  
  28. CImpIPolyline::CImpIPolyline(PCPolyline pObj, LPUNKNOWN pUnkOuter)
  29.     {
  30.     m_cRef=0;
  31.     m_pObj=pObj;
  32.     m_pUnkOuter=pUnkOuter;
  33.     return;
  34.     }
  35.  
  36.  
  37. CImpIPolyline::~CImpIPolyline(void)
  38.     {
  39.     return;
  40.     }
  41.  
  42.  
  43.  
  44.  
  45. /*
  46.  * CImpIPolyline::QueryInterface
  47.  * CImpIPolyline::AddRef
  48.  * CImpIPolyline::Release
  49.  */
  50.  
  51. STDMETHODIMP CImpIPolyline::QueryInterface(REFIID riid, PPVOID ppv)
  52.     {
  53.     return m_pUnkOuter->QueryInterface(riid, ppv);
  54.     }
  55.  
  56. STDMETHODIMP_(ULONG) CImpIPolyline::AddRef(void)
  57.     {
  58.     ++m_cRef;
  59.     return m_pUnkOuter->AddRef();
  60.     }
  61.  
  62. STDMETHODIMP_(ULONG) CImpIPolyline::Release(void)
  63.     {
  64.     --m_cRef;
  65.     return m_pUnkOuter->Release();
  66.     }
  67.  
  68.  
  69.  
  70.  
  71.  
  72. /*
  73.  * CImpIPolyline::Init
  74.  *
  75.  * Purpose:
  76.  *  Instantiates a polyline window within a given parent.  The
  77.  *  parent may be a main application window, could be an MDI child
  78.  *  window. We really do not care.
  79.  *
  80.  * Parameters:
  81.  *  hWndParent      HWND of the parent of this window
  82.  *  pRect           LPRECT that this window should occupy
  83.  *  dwStyle         DWORD containing the window's style flags
  84.  *  uID             UINT ID to associate with this window
  85.  *
  86.  * Return Value:
  87.  *  HRESULT         NOERROR if successful, otherwise E_OUTOFMEMORY
  88.  */
  89.  
  90. STDMETHODIMP CImpIPolyline::Init(HWND hWndParent, LPRECT pRect
  91.     , DWORD dwStyle, UINT uID)
  92.     {
  93.     SCODE           sc;
  94.  
  95.     m_pObj->m_hWnd=CreateWindowEx(WS_EX_NOPARENTNOTIFY
  96.         , SZCLASSPOLYLINE, SZCLASSPOLYLINE, dwStyle, pRect->left
  97.         , pRect->top, pRect->right-pRect->left
  98.         , pRect->bottom-pRect->top, hWndParent, (HMENU)uID
  99.         , m_pObj->m_hInst, m_pObj);
  100.  
  101.     sc=(NULL!=m_pObj->m_hWnd) ? S_OK : E_OUTOFMEMORY;
  102.     return ResultFromScode(sc);
  103.     }
  104.  
  105.  
  106.  
  107. //CHAPTER8MOD
  108. /*
  109.  * ReadFromFile and WriteToFile are replaced by the IPersistStorage
  110.  * implementation.  We no longer read from files, instead we use
  111.  * storages.
  112.  */
  113. //End CHAPTER8MOD
  114.  
  115.  
  116.  
  117.  
  118. /*
  119.  * CImpIPolyline::DataSet
  120.  *
  121.  * Purpose:
  122.  *  Sets the current data in this Polyline to a given structure.
  123.  *
  124.  * Parameters:
  125.  *  pplIn           PPOLYLINEDATA to initialize to.
  126.  *  fSizeToData     BOOL indicating if we're to size to the data
  127.  *                  or scale it.
  128.  *  fNotify         BOOL indicating if we're to send an advise
  129.  *                  on this change.
  130.  *
  131.  * Return Value:
  132.  *  HRESULT         NOERROR if successful, otherwise a
  133.  *                  POLYLINE_E_ value.
  134.  */
  135.  
  136. STDMETHODIMP CImpIPolyline::DataSet(PPOLYLINEDATA pplIn
  137.     , BOOL fSizeToData, BOOL fNotify)
  138.     {
  139.     PPOLYLINEDATA   ppl=&m_pObj->m_pl;
  140.     RECT            rc;
  141.  
  142.     /*
  143.      * Copy the structure in pplIn and repaint to reflect the
  144.      * new point set.  Note that unlike the RectSet message, we
  145.      * do no scaling, assuming that the rect in the structure
  146.      * is appropriate for the data.
  147.      */
  148.  
  149.     if (NULL==pplIn)
  150.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  151.  
  152.     *ppl=*pplIn;
  153.  
  154.     //Inform our parent of the data change
  155.     if (NULL!=m_pObj->m_pAdv)
  156.         {
  157.         m_pObj->m_fDirty=TRUE;
  158.         m_pObj->m_pAdv->OnDataChange();
  159.         }
  160.  
  161.     /*
  162.      * If we're scaling the window to fit the data, then use
  163.      * RectSet passing our current rectangle as the new one.
  164.      * That makes sure that the data won't change but that the
  165.      * window is resized.
  166.      */
  167.  
  168.     if (fSizeToData)
  169.         {
  170.         POINT       pt;
  171.  
  172.         /*
  173.          * Get our offset in the parent window so we can RectSet
  174.          * to the right place since RectSet expects rectangle in
  175.          * parent coordinates and we get it in client coordinates.
  176.          */
  177.         GetWindowRect(m_pObj->m_hWnd, &rc);
  178.         pt.x=rc.left;
  179.         pt.y=rc.top;
  180.         ScreenToClient(GetParent(m_pObj->m_hWnd), &pt);
  181.         RECTSTORECT(ppl->rc, rc);
  182.         OffsetRect(&rc, pt.x, pt.y);
  183.  
  184.         //This will also cause a repaint.
  185.         RectSet(&rc, fNotify);
  186.         }
  187.     else
  188.         {
  189.         //Make sure we're updated.
  190.         InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  191.         UpdateWindow(m_pObj->m_hWnd);
  192.         }
  193.  
  194.     return NOERROR;
  195.     }
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203. /*
  204.  * CImpIPolyline::DataGet
  205.  *
  206.  * Purpose:
  207.  *  Retrieves the Polyline's current data.
  208.  *
  209.  * Parameters:
  210.  *  pplIn           PPOLYLINEDATA into which we copy the data.
  211.  *
  212.  * Return Value:
  213.  *  HRESULT         NOERROR if successful, otherwise a
  214.  *                  POLYLINE_E_ value.
  215.  */
  216.  
  217. STDMETHODIMP CImpIPolyline::DataGet(PPOLYLINEDATA pplIn)
  218.     {
  219.     if (NULL==pplIn)
  220.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  221.  
  222.     *pplIn=m_pObj->m_pl;
  223.     return NOERROR;
  224.     }
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232. /*
  233.  * CImpIPolyline::DataSetMem
  234.  *
  235.  * Purpose:
  236.  *  Sets the Polyline's data using a global memory handle
  237.  *  instead of a pointer.
  238.  *
  239.  * Parameters:
  240.  *  hMem            HGLOBAL containing the data.
  241.  *  fFree           BOOL indicating if we're to free the data.
  242.  *                  The memory will be freed regardless of any
  243.  *                  error returned from here.
  244.  *  fSizeToData     BOOL indicating if we're to size to the data
  245.  *                  or scale it.
  246.  *  fNotify         BOOL indicating if we're to send an advise
  247.  *                  on this change.
  248.  *
  249.  * Return Value:
  250.  *  HRESULT         NOERROR if successful, otherwise a
  251.  *                  POLYLINE_E_ value.
  252.  */
  253.  
  254. STDMETHODIMP CImpIPolyline::DataSetMem(HGLOBAL hMem, BOOL fFree
  255.     , BOOL fSizeToData, BOOL fNotify)
  256.     {
  257.     PPOLYLINEDATA   ppl;
  258.     HRESULT         hr=ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  259.  
  260.     if (NULL!=hMem)
  261.         {
  262.         ppl=(PPOLYLINEDATA)GlobalLock(hMem);
  263.         hr=DataSet(ppl, fSizeToData, fNotify);
  264.  
  265.         GlobalUnlock(hMem);
  266.  
  267.         if (fFree)
  268.             GlobalFree(hMem);
  269.         }
  270.  
  271.     return hr;
  272.     }
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280. /*
  281.  * CImpIPolyline::DataGetMem
  282.  *
  283.  * Purpose:
  284.  *  Retrieves the Polyline's data in a global memory handle.
  285.  *
  286.  * Parameters:
  287.  *  phMem           HGLOBAL * in which to store the handle.
  288.  *
  289.  * Return Value:
  290.  *  HRESULT         NOERROR if successful, otherwise a
  291.  *                  POLYLINE_E_ value.
  292.  */
  293.  
  294. STDMETHODIMP CImpIPolyline::DataGetMem(HGLOBAL *phMem)
  295.     {
  296.     HGLOBAL         hMem;
  297.     PPOLYLINEDATA   ppl;
  298.     HRESULT         hr=ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  299.  
  300.     if (NULL==phMem)
  301.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  302.  
  303.     hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, CBPOLYLINEDATA);
  304.  
  305.     if (NULL!=hMem)
  306.         {
  307.         ppl=(PPOLYLINEDATA)GlobalLock(hMem);
  308.         hr=DataGet(ppl);
  309.  
  310.         GlobalUnlock(hMem);
  311.  
  312.         if (FAILED(hr))
  313.             {
  314.             GlobalFree(hMem);
  315.             hMem=NULL;
  316.             }
  317.         }
  318.  
  319.     *phMem=hMem;
  320.     return hr;
  321.     }
  322.  
  323.  
  324.  
  325.  
  326. /*
  327.  * CImpIPolyline::RenderBitmap
  328.  *
  329.  * Purpose:
  330.  *  Creates a bitmap image of the current Polyline.
  331.  *
  332.  * Parameters:
  333.  *  phBmp           HBITMAP * in which to return the bitmap.
  334.  *
  335.  * Return Value:
  336.  *  HRESULT         NOERROR if successful, otherwise a
  337.  *                  POLYLINE_E_ value.
  338.  */
  339.  
  340. STDMETHODIMP CImpIPolyline::RenderBitmap(HBITMAP *phBmp)
  341.     {
  342.     HDC             hDC;
  343.     HDC             hMemDC;
  344.     HBITMAP         hBmp;
  345.     RECT            rc;
  346.     HGDIOBJ         hObj;
  347.  
  348.     if (NULL==phBmp)
  349.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  350.  
  351.     //Render a bitmap the size of the current rectangle.
  352.     hDC=GetDC(m_pObj->m_hWnd);
  353.     hMemDC=CreateCompatibleDC(hDC);
  354.  
  355.     GetClientRect(m_pObj->m_hWnd, &rc);
  356.     hBmp=CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
  357.  
  358.     if (NULL!=hBmp)
  359.         {
  360.         //Draw the POLYLINEDATA into the bitmap.
  361.         hObj=SelectObject(hMemDC, hBmp);
  362.         m_pObj->Draw(hMemDC, FALSE, TRUE);
  363.         SelectObject(hMemDC, hObj);
  364.         }
  365.  
  366.     DeleteDC(hMemDC);
  367.     ReleaseDC(m_pObj->m_hWnd, hDC);
  368.  
  369.     *phBmp=hBmp;
  370.     return NOERROR;
  371.     }
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379. /*
  380.  * CImpIPolyline::RenderMetafile
  381.  *
  382.  * Purpose:
  383.  *  Renders the current image of the Polyline into a metafile.
  384.  *
  385.  * Parameters:
  386.  *  phMF            HMETAFILE * in which to return the
  387.  *                  new metafile.
  388.  *
  389.  * Return Value:
  390.  *  HRESULT         NOERROR if successful, otherwise a
  391.  *                  POLYLINE_E_ value.
  392.  */
  393.  
  394. STDMETHODIMP CImpIPolyline::RenderMetafile(HMETAFILE *phMF)
  395.     {
  396.     HDC             hDC;
  397.     HMETAFILE       hMF;
  398.     RECT            rc;
  399.  
  400.     if (NULL==phMF)
  401.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  402.  
  403.     //Create a memory metafile and return its handle.
  404.     hDC=(HDC)CreateMetaFile(NULL);
  405.     hMF=NULL;
  406.  
  407.     if (NULL!=hDC)
  408.         {
  409.         /*
  410.          * This is absolutely essential to the metafile so it
  411.          * can be scaled in the clipboard and any destination
  412.          * application.
  413.          */
  414.         SetMapMode(hDC, MM_ANISOTROPIC);
  415.         GetClientRect(m_pObj->m_hWnd, &rc);
  416.         SetWindowOrgEx(hDC, 0, 0, NULL);
  417.         SetWindowExtEx(hDC, rc.right, rc.bottom, NULL);
  418.  
  419.         m_pObj->Draw(hDC, TRUE, TRUE);
  420.         hMF=CloseMetaFile(hDC);
  421.         }
  422.  
  423.     *phMF=hMF;
  424.     return NOERROR;
  425.     }
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432. /*
  433.  * CImpIPolyline::RenderMetafilePict
  434.  *
  435.  * Purpose:
  436.  *  Renders the current Polyline into a METAFILEPICT structure in
  437.  *  global memory.
  438.  *
  439.  * Parameters:
  440.  *  phMem           HGLOBAL * in which to return the
  441.  *                  METAFILEPICT.
  442.  *
  443.  * Return Value:
  444.  *  HRESULT         NOERROR if successful, otherwise a
  445.  *                  POLYLINE_E_ value.
  446.  */
  447.  
  448. STDMETHODIMP CImpIPolyline::RenderMetafilePict(HGLOBAL *phMem)
  449.     {
  450.     HGLOBAL         hMem;
  451.     HMETAFILE       hMF;
  452.     LPMETAFILEPICT  pMF;
  453.     RECT            rc;
  454.     HRESULT         hr;
  455.  
  456.     if (NULL==phMem)
  457.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  458.  
  459.     //Get the metafile
  460.     hr=RenderMetafile(&hMF);
  461.  
  462.     if (FAILED(hr))
  463.         return hr;
  464.  
  465.     //Allocate the METAFILEPICT structure.
  466.     hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE
  467.         , sizeof(METAFILEPICT));
  468.  
  469.     if (NULL==hMem)
  470.         {
  471.         DeleteMetaFile(hMF);
  472.         return ResultFromScode(E_FAIL);
  473.         }
  474.  
  475.     /*
  476.      * Global lock only fails in PMODE if the selector is invalid
  477.      * (like it was discarded) or references a 0 length segment,
  478.      * neither of which can happen here.
  479.      */
  480.     pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  481.  
  482.     pMF->hMF=hMF;
  483.     pMF->mm=MM_ANISOTROPIC;
  484.  
  485.     //Insert the extents in MM_HIMETRIC units.
  486.     GetClientRect(m_pObj->m_hWnd, &rc);
  487.     m_pObj->RectConvertMappings(&rc, FALSE);
  488.     pMF->xExt=rc.right;
  489.     pMF->yExt=rc.bottom;
  490.  
  491.     GlobalUnlock(hMem);
  492.  
  493.     *phMem=hMem;
  494.     return NOERROR;
  495.     }
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505. /*
  506.  * CImpIPolyline::New
  507.  *
  508.  * Purpose:
  509.  *  Cleans out and reinitializes the data to defaults.
  510.  *
  511.  * Parameters:
  512.  *  None
  513.  *
  514.  * Return Value:
  515.  *  HRESULT         NOERROR always
  516.  */
  517.  
  518. STDMETHODIMP CImpIPolyline::New(void)
  519.     {
  520.     PPOLYLINEDATA   ppl=&m_pObj->m_pl;
  521.     UINT            i;
  522.     RECT            rc;
  523.  
  524.     ppl->wVerMaj=VERSIONMAJOR;
  525.     ppl->wVerMin=VERSIONMINOR;
  526.  
  527.     //Our rectangle is the size of our window's client area.
  528.     GetClientRect(m_pObj->m_hWnd, &rc);
  529.     RECTTORECTS(rc, ppl->rc);
  530.  
  531.     //Clean out the POLYLINEDATA structure and repaint the window.
  532.     for (i=0; i< CPOLYLINEPOINTS; i++)
  533.         {
  534.         ppl->rgpt[i].x=0;
  535.         ppl->rgpt[i].y=0;
  536.         }
  537.  
  538.     ppl->cPoints      =0;
  539.     ppl->rgbBackground=GetSysColor(COLOR_WINDOW);
  540.     ppl->rgbLine      =GetSysColor(COLOR_WINDOWTEXT);
  541.     ppl->iLineStyle   =PS_SOLID;
  542.  
  543.     InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  544.     UpdateWindow(m_pObj->m_hWnd);
  545.  
  546.     //Inform the advise sink of this data change.
  547.     if (NULL!=m_pObj->m_pAdv)
  548.         {
  549.         m_pObj->m_fDirty=TRUE;
  550.         m_pObj->m_pAdv->OnDataChange();
  551.         }
  552.  
  553.     return NOERROR;
  554.     }
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561. /*
  562.  * CImpIPolyline::Undo
  563.  *
  564.  * Purpose:
  565.  *  Reverses previous actions in a Polyline.
  566.  *
  567.  * Parameters:
  568.  *  None
  569.  *
  570.  * Return Value:
  571.  *  HRESULT         S_OK if we can Undo more, S_FALSE otherwise.
  572.  */
  573.  
  574. STDMETHODIMP CImpIPolyline::Undo(void)
  575.     {
  576.     SCODE           sc;
  577.  
  578.     //Decrement the number of active points and repaint.
  579.     if (m_pObj->m_pl.cPoints > 0)
  580.         {
  581.         m_pObj->m_pl.cPoints--;
  582.         InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  583.         UpdateWindow(m_pObj->m_hWnd);
  584.         }
  585.  
  586.     if (NULL!=m_pObj->m_pAdv)
  587.         {
  588.         m_pObj->m_fDirty=TRUE;
  589.         m_pObj->m_pAdv->OnPointChange();
  590.         }
  591.  
  592.     //Return if we can undo any more.
  593.     sc=(0!=m_pObj->m_pl.cPoints) ? S_OK : S_FALSE;
  594.     return ResultFromScode(sc);
  595.     }
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602. /*
  603.  * CImpIPolyline::Window
  604.  *
  605.  * Purpose:
  606.  *  Returns the window handle associated with this polyline.
  607.  *
  608.  * Parameters:
  609.  *  phWnd           HWND * in which to return the window handle.
  610.  *
  611.  * Return Value:
  612.  *  HRESULT         NOERROR always.
  613.  */
  614.  
  615. STDMETHODIMP CImpIPolyline::Window(HWND *phWnd)
  616.     {
  617.     *phWnd=m_pObj->m_hWnd;
  618.     return NOERROR;
  619.     }
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626. /*
  627.  * CImpIPolyline::RectGet
  628.  *
  629.  * Purpose:
  630.  *  Returns the rectangle of the Polyline in parent coordinates.
  631.  *
  632.  * Parameters:
  633.  *  pRect           LPRECT in which to return the rectangle.
  634.  *
  635.  * Return Value:
  636.  *  HRESULT         NOERROR always
  637.  */
  638.  
  639. STDMETHODIMP CImpIPolyline::RectGet(LPRECT pRect)
  640.     {
  641.     RECT            rc;
  642.     POINT           pt;
  643.  
  644.     //Retrieve the size of our rectangle in parent coordinates.
  645.     GetWindowRect(m_pObj->m_hWnd, &rc);
  646.     pt.x=rc.left;
  647.     pt.y=rc.top;
  648.     ScreenToClient(GetParent(m_pObj->m_hWnd), &pt);
  649.  
  650.     SetRect(pRect, pt.x, pt.y, pt.x+(rc.right-rc.left)
  651.         , pt.y+(rc.bottom-rc.top));
  652.  
  653.     return NOERROR;
  654.     }
  655.  
  656.  
  657.  
  658.  
  659.  
  660. /*
  661.  * CImpIPolyline::SizeGet
  662.  *
  663.  * Purpose:
  664.  *  Retrieves the size of the Polyline in parent coordinates.
  665.  *
  666.  * Parameters:
  667.  *  pRect           LPRECT in which to return the size.  The right
  668.  *                  and bottom fields will contain the dimensions.
  669.  *
  670.  * Return Value:
  671.  *  HRESULT         NOERROR always
  672.  */
  673.  
  674. STDMETHODIMP CImpIPolyline::SizeGet(LPRECT pRect)
  675.     {
  676.     RectGet(pRect);
  677.     return NOERROR;
  678.     }
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685. /*
  686.  * CImpIPolyline::RectSet
  687.  *
  688.  * Purpose:
  689.  *  Sets a new rectangle for the Polyline which sizes to fit.
  690.  *
  691.  * Parameters:
  692.  *  pRect           LPRECT containing the new rectangle.
  693.  *  fNotify         BOOL indicating if we're to notify anyone of
  694.  *                  the change.
  695.  *
  696.  * Return Value:
  697.  *  HRESULT         NOERROR always
  698.  */
  699.  
  700. STDMETHODIMP CImpIPolyline::RectSet(LPRECT pRect, BOOL fNotify)
  701.     {
  702.     UINT            cx, cy;
  703.     RECT            rc;
  704.  
  705.     //Scale the points from our current size to the new size
  706.     cx=pRect->right-pRect->left;
  707.     cy=pRect->bottom-pRect->top;
  708.  
  709.     SetWindowPos(m_pObj->m_hWnd, NULL, pRect->left, pRect->top
  710.         , cx, cy, SWP_NOZORDER);
  711.  
  712.     SetRect(&rc, 0, 0, cx, cy);
  713.     RECTTORECTS(rc, m_pObj->m_pl.rc);
  714.  
  715.     if (fNotify && NULL!=m_pObj->m_pAdv)
  716.         {
  717.         m_pObj->m_fDirty=TRUE;
  718.         m_pObj->m_pAdv->OnSizeChange();
  719.         }
  720.  
  721.     InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  722.  
  723.     return NOERROR;
  724.     }
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732. /*
  733.  * CImpIPolyline::SizeSet
  734.  *
  735.  * Purpose:
  736.  *  Sets a new size for the Polyline which sizes to fit.
  737.  *
  738.  * Parameters:
  739.  *  pRect           LPRECT containing the new rectangle.
  740.  *  fNotify         BOOL indicating if we're to notify anyone of
  741.  *                  the change.
  742.  *
  743.  * Return Value:
  744.  *  HRESULT         NOERROR always
  745.  */
  746.  
  747. STDMETHODIMP CImpIPolyline::SizeSet(LPRECT pRect, BOOL fNotify)
  748.     {
  749.     UINT            cx, cy;
  750.  
  751.     //Scale the points from our current size to the new size
  752.     cx=pRect->right-pRect->left;
  753.     cy=pRect->bottom-pRect->top;
  754.  
  755.     SetWindowPos(m_pObj->m_hWnd, NULL, 0, 0, (UINT)cx, (UINT)cy
  756.         , SWP_NOMOVE | SWP_NOZORDER);
  757.  
  758.     if (fNotify && NULL!=m_pObj->m_pAdv)
  759.         {
  760.         m_pObj->m_fDirty=TRUE;
  761.         m_pObj->m_pAdv->OnSizeChange();
  762.         }
  763.  
  764.     InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  765.  
  766.     return NOERROR;
  767.     }
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774. /*
  775.  * CImpIPolyline::ColorSet
  776.  *
  777.  * Purpose:
  778.  *  Changes for background or line color in the Polyline
  779.  *
  780.  * Parameters:
  781.  *  iColor          UINT index of the color to change.
  782.  *  cr              COLORREF new color to use.
  783.  *  pcrPrev         COLORREF * in whch to store the
  784.  *                  previous color.
  785.  *
  786.  * Return Value:
  787.  *  HRESULT         NOERROR if successful, otherwise a
  788.  *                  POLYLINE_E_ value.
  789.  */
  790.  
  791. STDMETHODIMP CImpIPolyline::ColorSet(UINT iColor, COLORREF cr
  792.     , COLORREF *pcrPrev)
  793.     {
  794.     COLORREF        crRet;
  795.  
  796.     if (NULL==pcrPrev)
  797.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  798.  
  799.     switch (iColor)
  800.         {
  801.         case POLYLINECOLOR_BACKGROUND:
  802.             crRet=m_pObj->m_pl.rgbBackground;
  803.             m_pObj->m_pl.rgbBackground=cr;
  804.             break;
  805.  
  806.         case POLYLINECOLOR_LINE:
  807.             crRet=m_pObj->m_pl.rgbLine;
  808.             m_pObj->m_pl.rgbLine=cr;
  809.             break;
  810.         }
  811.  
  812.     //If the color changed, repaint
  813.     if (crRet!=cr)
  814.         {
  815.         if (NULL!=m_pObj->m_pAdv)
  816.             {
  817.             m_pObj->m_fDirty=TRUE;
  818.             m_pObj->m_pAdv->OnColorChange();
  819.             }
  820.  
  821.         InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  822.         UpdateWindow(m_pObj->m_hWnd);
  823.         }
  824.  
  825.     *pcrPrev=crRet;
  826.     return NOERROR;
  827.     }
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835. /*
  836.  * CImpIPolyline::ColorGet
  837.  *
  838.  * Purpose:
  839.  *  Retrieves one of the colors currently in use by the Polyline.
  840.  *
  841.  * Parameters:
  842.  *  iColor          UINT identifying the color of interest.
  843.  *  pcr             COLORREF * in which to return the color.
  844.  *
  845.  * Return Value:
  846.  *  HRESULT         NOERROR if successful, otherwise a
  847.  *                  POLYLINE_E_ value.
  848.  */
  849.  
  850. STDMETHODIMP CImpIPolyline::ColorGet(UINT iColor, COLORREF *pcr)
  851.     {
  852.     COLORREF        crRet;
  853.  
  854.     if (NULL==pcr)
  855.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  856.  
  857.     crRet=(POLYLINECOLOR_BACKGROUND==iColor)
  858.         ? m_pObj->m_pl.rgbBackground : m_pObj->m_pl.rgbLine;
  859.  
  860.     *pcr=crRet;
  861.     return NOERROR;
  862.     }
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871. /*
  872.  * CImpIPolyline::LineStyleSet
  873.  *
  874.  * Purpose:
  875.  *  Changes the line style in use by the Polyline
  876.  *
  877.  * Parameters:
  878.  *  iStyle          UINT style of the line to use.
  879.  *  piPrev          UINT * in which to store the previous style.
  880.  *
  881.  * Return Value:
  882.  *  HRESULT         NOERROR if successful, otherwise a
  883.  *                  POLYLINE_E_ value.
  884.  */
  885.  
  886. STDMETHODIMP CImpIPolyline::LineStyleSet(UINT iStyle, UINT *piPrev)
  887.     {
  888.     UINT            uRet;
  889.  
  890.     uRet=(UINT)m_pObj->m_pl.iLineStyle;
  891.  
  892.     if (NULL==piPrev)
  893.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  894.  
  895.     //Validate the line style
  896.     if (PS_SOLID==iStyle || PS_DASH==iStyle || PS_DOT==iStyle
  897.         || PS_DASHDOT==iStyle || PS_DASHDOTDOT==iStyle)
  898.         {
  899.         m_pObj->m_pl.iLineStyle=iStyle;
  900.  
  901.         if (uRet!=(UINT)m_pObj->m_pl.iLineStyle)
  902.             {
  903.             if (NULL!=m_pObj->m_pAdv)
  904.                 {
  905.                 m_pObj->m_fDirty=TRUE;
  906.                 m_pObj->m_pAdv->OnLineStyleChange();
  907.                 }
  908.  
  909.             InvalidateRect(m_pObj->m_hWnd, NULL, TRUE);
  910.             UpdateWindow(m_pObj->m_hWnd);
  911.             }
  912.         }
  913.  
  914.     *piPrev=uRet;
  915.     return NOERROR;
  916.     }
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924. /*
  925.  * CImpIPolyline::LineStyleGet
  926.  *
  927.  * Purpose:
  928.  *  Retrieves the current line style in use in the Polyline
  929.  *
  930.  * Parameters:
  931.  *  piStyle         UINT * in which to store the style.
  932.  *
  933.  * Return Value:
  934.  *  HRESULT         NOERROR if successful, otherwise a
  935.  *                  POLYLINE_E_ value.
  936.  */
  937.  
  938. STDMETHODIMP CImpIPolyline::LineStyleGet(UINT *piStyle)
  939.     {
  940.     if (NULL==piStyle)
  941.         return ResultFromScode(POLYLINE_E_INVALIDPOINTER);
  942.  
  943.     *piStyle=m_pObj->m_pl.iLineStyle;
  944.     return NOERROR;
  945.     }
  946.