home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / oleaut / lines / line.cpp < prev    next >
C/C++ Source or Header  |  1997-09-20  |  10KB  |  456 lines

  1. /*************************************************************************
  2. **
  3. **  This is a part of the Microsoft Source Code Samples.
  4. **
  5. **  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  6. **
  7. **  This source code is only intended as a supplement to Microsoft Development
  8. **  Tools and/or WinHelp documentation.  See these sources for detailed
  9. **  information regarding the Microsoft samples programs.
  10. **
  11. **  OLE Automation Lines Object.
  12. **
  13. **  line.cpp
  14. **
  15. **  CLine implementation
  16. **
  17. **  Written by Microsoft Product Support Services, Windows Developer Support
  18. **
  19. *************************************************************************/
  20.  
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #ifdef WIN16   
  24.   #include <ole2.h>
  25.   #include <compobj.h>    
  26.   #include <dispatch.h> 
  27.   #include <variant.h>
  28.   #include <olenls.h>  
  29. #endif      
  30. #include "lines.h"
  31.  
  32. /*
  33.  * CLine::Create
  34.  *
  35.  * Purpose:
  36.  *  Creates an instance of the Line automation object and initializes it.
  37.  *
  38.  * Parameters:
  39.  *  ppLine    Returns Line automation object.
  40.  *
  41.  * Return Value:
  42.  *  HRESULT
  43.  *
  44.  */
  45. HRESULT 
  46. CLine::Create(CLine FAR* FAR* ppLine ) 
  47. {   
  48.     HRESULT hr;
  49.     CLine FAR* pLine = NULL;
  50.      
  51.     *ppLine = NULL;
  52.     
  53.     pLine = new CLine();
  54.     if (pLine == NULL)
  55.         goto error;        
  56.     
  57.     // Load type information for the line from type library. 
  58.     hr = LoadTypeInfo(&pLine->m_ptinfo, IID_ILine);
  59.     if (FAILED(hr))
  60.         goto error;
  61.  
  62.     *ppLine = pLine;
  63.     return NOERROR;
  64.     
  65. error:                        
  66.     if (pLine == NULL)
  67.         return E_OUTOFMEMORY; 
  68.                     
  69.     if (pLine->m_ptinfo)
  70.         pLine->m_ptinfo->Release();
  71.     
  72.     // Set to NULL to prevent destructor from attempting to free again
  73.     pLine->m_ptinfo = NULL; 
  74.     
  75.     delete pLine;
  76.     return hr;
  77. }
  78.  
  79. /*
  80.  * CLine::CLine
  81.  *
  82.  * Purpose:
  83.  *  Constructor for CLine object. Initializes members to NULL.
  84.  *
  85.  */
  86. #pragma warning (disable : 4355)
  87. CLine::CLine() : m_SupportErrorInfo(this, IID_ILine)
  88. #pragma warning (default : 4355)
  89. {   
  90.     m_ptinfo = NULL;
  91.     m_pPointStart = NULL;
  92.     m_pPointEnd = NULL;
  93.     m_nThickness = 0;  
  94.     m_colorref = 0;    
  95.     m_cRef = 0;  
  96. }
  97.  
  98. /*
  99.  * CLine::~CLine
  100.  *
  101.  * Purpose:
  102.  *  Destructor for CLine object.
  103.  *
  104.  */
  105. CLine::~CLine()
  106. {            
  107.      if (m_ptinfo) m_ptinfo->Release(); 
  108.      if (m_pPointStart) m_pPointStart->Release();
  109.      if (m_pPointEnd) m_pPointEnd->Release(); 
  110. }
  111.  
  112. /*
  113.  * CLine::QueryInterface, AddRef, Release
  114.  *
  115.  * Purpose:
  116.  *  Implements IUnknown::QueryInterface, AddRef, Release
  117.  *
  118.  */
  119. STDMETHODIMP
  120. CLine::QueryInterface(REFIID iid, void FAR* FAR* ppv) 
  121. {   
  122.     *ppv = NULL;
  123.     
  124.     if (iid == IID_IUnknown || iid == IID_IDispatch || iid == IID_ILine)
  125.         *ppv = this; 
  126.     else if (iid == IID_ISupportErrorInfo)
  127.         *ppv = &m_SupportErrorInfo;
  128.     else return E_NOINTERFACE; 
  129.  
  130.     AddRef();
  131.     return NOERROR;    
  132. }
  133.  
  134.  
  135. STDMETHODIMP_(ULONG)
  136. CLine::AddRef(void)
  137. {  
  138.  
  139. #ifdef _DEBUG  
  140.     TCHAR ach[50];
  141.     wsprintf(ach, TEXT("Ref = %ld, Line\r\n"), m_cRef+1); 
  142.     OutputDebugString(ach); 
  143. #endif  
  144.  
  145.     return ++m_cRef;
  146. }
  147.  
  148. STDMETHODIMP_(ULONG)
  149. CLine::Release(void)
  150. {    
  151. #ifdef _DEBUG  
  152.     TCHAR ach[50];
  153.     wsprintf(ach, TEXT("Ref = %ld, Line\r\n"), m_cRef-1); 
  154.     OutputDebugString(ach);   
  155. #endif
  156.  
  157.     if(--m_cRef == 0)
  158.     {
  159.         delete this;
  160.         return 0;
  161.     }
  162.     return m_cRef;
  163. }
  164.  
  165. /*
  166.  * CLine::GetTypeInfoCount
  167.  *
  168.  * Purpose:
  169.  *  Implements IDispatch::GetTypeInfoCount.
  170.  *
  171.  */
  172. STDMETHODIMP
  173. CLine::GetTypeInfoCount(UINT FAR* pctinfo)
  174. {
  175.     *pctinfo = 1;
  176.     return NOERROR;
  177. }
  178.  
  179. /*
  180.  * CLine::GetTypeInfo
  181.  *
  182.  * Purpose:
  183.  *  Implements IDispatch::GetTypeInfo. 
  184.  *
  185.  */
  186. STDMETHODIMP
  187. CLine::GetTypeInfo(
  188.       UINT itinfo,
  189.       LCID lcid,
  190.       ITypeInfo FAR* FAR* pptinfo)
  191. {    
  192.     *pptinfo = NULL;
  193.      
  194.     if(itinfo != 0)
  195.         return DISP_E_BADINDEX;
  196.     
  197.     m_ptinfo->AddRef(); 
  198.     *pptinfo = m_ptinfo;
  199.     
  200.     return NOERROR;
  201. }
  202.  
  203. /*
  204.  * CLine::GetIDsOfNames
  205.  *
  206.  * Purpose:
  207.  *  Implements IDispatch::GetIDsOfNames.  The standard implementation, DispGetIDsOfNames,
  208.  *  is used.
  209.  *
  210.  */
  211. STDMETHODIMP 
  212. CLine::GetIDsOfNames(
  213.       REFIID riid,
  214.       OLECHAR FAR* FAR* rgszNames,
  215.       UINT cNames,
  216.       LCID lcid,
  217.       DISPID FAR* rgdispid)
  218. {
  219.     return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);
  220. }
  221.  
  222. /*
  223.  * CLine::Invoke
  224.  *
  225.  * Purpose:
  226.  *  Implements IDispatch::Invoke.  The standard implementation, DispInvoke,
  227.  *  is used. 
  228.  *
  229.  */
  230. STDMETHODIMP
  231. CLine::Invoke(
  232.       DISPID dispidMember,
  233.       REFIID riid,
  234.       LCID lcid,
  235.       WORD wFlags,
  236.       DISPPARAMS FAR* pdispparams,
  237.       VARIANT FAR* pvarResult,
  238.       EXCEPINFO FAR* pexcepinfo,
  239.       UINT FAR* puArgErr)
  240. {  
  241.     // VB 3.0/Disptest have a bug in which they pass DISPATCH_PROPERTYPUT
  242.     // instead of DISPATCH_PROPERTYPUTREF for the EndPoint and StartPoint
  243.     // properties. Future versions of VB will correctly pass DISPATCH_PROPERTYPUTREF.
  244.     // EndPoint has DISPID == 1 and StartPoint has DISPID == 2 - see lines.odl. 
  245.     // The following code works around the VB 3.0/Disptest bug. 
  246.     if ((dispidMember == 1 || dispidMember == 2)
  247.         && wFlags == DISPATCH_PROPERTYPUT)
  248.         wFlags = DISPATCH_PROPERTYPUTREF;
  249.  
  250.     return DispInvoke(
  251.         this, m_ptinfo,
  252.         dispidMember, wFlags, pdispparams,
  253.         pvarResult, pexcepinfo, puArgErr); 
  254.  
  255. /*  
  256.  * 
  257.  * Properties and methods exposed through automation.
  258.  *
  259.  */
  260. STDMETHODIMP
  261. CLine::get_Color(long FAR* plColorref)
  262. {
  263.     *plColorref =  m_colorref;   
  264.     return NOERROR;
  265. }
  266.  
  267. STDMETHODIMP
  268. CLine::put_Color(long lColorref)
  269. {
  270.     m_colorref = (COLORREF)lColorref;  
  271.     return NOERROR;
  272. }
  273.  
  274. STDMETHODIMP
  275. CLine::get_EndPoint(IPoint FAR* FAR* ppPoint)
  276. {   
  277.     HRESULT hr;       
  278.     
  279.     *ppPoint = NULL;
  280.     
  281.     if (NULL == m_pPointEnd)  
  282.         return RaiseException(IDS_NoStartPoint, IID_ILine);                      
  283.     
  284.     hr = m_pPointEnd->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoint);
  285.     if (FAILED(hr))
  286.         return RaiseException(IDS_Unexpected, IID_ILine); 
  287.     return NOERROR; 
  288. }
  289.  
  290. STDMETHODIMP
  291. CLine::putref_EndPoint(IPoint FAR* pPointNew)
  292. {   
  293.     HRESULT hr;
  294.     CPoint FAR* pPoint;
  295.     
  296.     // Save the IPoint interface so we can easily access private data
  297.     hr = pPointNew->QueryInterface(IID_IPoint, (void FAR* FAR*)&pPoint);
  298.     if (FAILED(hr))
  299.         return RaiseException(IDS_PointFromOtherInstance, IID_ILine);    
  300.         
  301.     // Replace the old point with the new
  302.     if (m_pPointEnd)
  303.        m_pPointEnd->Release();    
  304.  
  305.     m_pPointEnd = pPoint;   
  306.     return NOERROR;
  307. }          
  308.  
  309. STDMETHODIMP
  310. CLine::get_StartPoint(IPoint FAR* FAR* ppPoint)
  311. {   
  312.     HRESULT hr;     
  313.     
  314.     *ppPoint = NULL;
  315.     
  316.     if (NULL == m_pPointStart)  
  317.         return RaiseException(IDS_NoStartPoint, IID_ILine);              
  318.     
  319.     hr = m_pPointStart->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoint);
  320.     if (FAILED(hr))
  321.         return RaiseException(IDS_Unexpected, IID_ILine); 
  322.  
  323.     return NOERROR;
  324. }
  325.  
  326. STDMETHODIMP
  327. CLine::putref_StartPoint(IPoint FAR* pPointNew)
  328. {
  329.     HRESULT hr;
  330.     CPoint FAR* pPoint;
  331.     
  332.     // Save the IPoint interface so we can easily access private data
  333.     hr = pPointNew->QueryInterface(IID_IPoint, (void FAR* FAR*)&pPoint);
  334.     if (FAILED(hr))
  335.         return RaiseException(IDS_PointFromOtherInstance, IID_ILine);   
  336.         
  337.     // Replace the old point with the new
  338.     if (m_pPointStart)
  339.        m_pPointStart->Release();    
  340.  
  341.     m_pPointStart = pPoint;   
  342.     return NOERROR;
  343. }
  344.  
  345. STDMETHODIMP
  346. CLine::get_Thickness(int FAR* pnThickness)
  347. {
  348.     *pnThickness = m_nThickness;
  349.     return NOERROR;
  350. }
  351.  
  352. STDMETHODIMP
  353. CLine::put_Thickness(int nThickness)
  354. {
  355.     m_nThickness = nThickness;  
  356.     return NOERROR;
  357. }
  358.  
  359. /* 
  360.  *
  361.  * The following methods are not exposed through Automation
  362.  *
  363.  */  
  364.  
  365. STDMETHODIMP_(void)
  366. CLine::Draw(HDC hdc)
  367. {
  368.     HPEN hpen, hpenOld;
  369.     
  370.     if (m_pPointStart == NULL)
  371.         return;
  372.     if (m_pPointEnd == NULL)
  373.         return;
  374.     
  375.     hpen = CreatePen(PS_SOLID, m_nThickness, m_colorref);
  376.     hpenOld = (HPEN) (HGDIOBJ)SelectObject(hdc, (HGDIOBJ)hpen);          
  377.       
  378.     MoveToEx(hdc, m_pPointStart->get_x(), m_pPointStart->get_y(), NULL);
  379.     LineTo(hdc, m_pPointEnd->get_x(), m_pPointEnd->get_y());
  380.     
  381.     SelectObject(hdc, (HGDIOBJ)hpenOld);
  382.     DeleteObject((HGDIOBJ)hpen);     
  383.     return;                 
  384. }
  385.  
  386. /*
  387.  * CLine::GetInvalidateRect
  388.  *
  389.  * Purpose:
  390.  *  Get the rectangle that cicumscribes the line. This rectangle is used to invalidate the area
  391.  *  of the window where the line is to be draw or erased.
  392.  *
  393.  */
  394. STDMETHODIMP_(void)
  395. CLine::GetInvalidateRect(LPRECT prc)
  396. {    
  397.     int nX1, nY1, nX2, nY2;
  398.    
  399.     nX1 = m_pPointStart->get_x();
  400.     nY1 = m_pPointStart->get_y();
  401.   
  402.     nX2 = m_pPointEnd->get_x();
  403.     nY2 = m_pPointEnd->get_y();
  404.     
  405.     if (nX1 < nX2)
  406.     {
  407.         prc->left = nX1;
  408.         prc->right = nX2;
  409.     }
  410.     else 
  411.     {    
  412.         prc->left = nX2;
  413.         prc->right = nX1;     
  414.     }
  415.     if (nY1 < nY2)
  416.     {
  417.         prc->top = nY1;
  418.         prc->bottom = nY2;
  419.     }
  420.     else 
  421.     {    
  422.         prc->top = nY2;
  423.         prc->bottom = nY1;     
  424.     }  
  425.  
  426.     InflateRect(prc, m_nThickness, m_nThickness);
  427.  
  428. STDMETHODIMP_(BOOL)
  429. CLine::AddEndPointsToPane(CPane FAR* pPane)
  430.     // Does the line have end points?
  431.     if (NULL == m_pPointStart)
  432.        return FALSE;
  433.     if (NULL == m_pPointEnd)
  434.        return FALSE;
  435.     
  436.     // Add points to Point collection in the Pane object.
  437.     if (pPane->AddPoint(m_pPointStart))
  438.         return pPane->AddPoint(m_pPointEnd); 
  439.     return FALSE;
  440.  
  441. }
  442.  
  443. STDMETHODIMP_(void)
  444. CLine::RemoveEndPointsFromPane(CPane FAR* pPane)
  445. {    
  446.     // Remove the end points of the line to be removed from the Points collection in the Pane.      
  447.     if (NULL != m_pPointStart)
  448.         pPane->RemovePoint(m_pPointStart);
  449.     if (NULL != m_pPointEnd)
  450.        pPane->RemovePoint(m_pPointEnd);   
  451.  
  452. }    
  453.