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 / enumvar.cpp < prev    next >
C/C++ Source or Header  |  1997-07-31  |  6KB  |  265 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. **  enumvar.cpp
  14. **
  15. **  CEnumVariant 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.  * CEnumVariant::Create
  34.  *
  35.  * Purpose:
  36.  *  Creates an instance of the IEnumVARIANT enumerator object and initializes it.
  37.  *
  38.  * Parameters:
  39.  *  psa        Safe array containing items to be enumerated.
  40.  *  cElements  Number of items to be enumerated. 
  41.  *  ppenumvariant    Returns enumerator object.
  42.  *
  43.  * Return Value:
  44.  *  HRESULT
  45.  *
  46.  */
  47. HRESULT
  48. CEnumVariant::Create(SAFEARRAY FAR* psa, ULONG cElements, CEnumVariant FAR* FAR* ppenumvariant) 
  49. {   
  50.     HRESULT hr;
  51.     CEnumVariant FAR* penumvariant = NULL;
  52.     long lLBound;
  53.                       
  54.     *ppenumvariant = NULL;
  55.     
  56.     penumvariant = new CEnumVariant();
  57.     if (penumvariant == NULL)
  58.         goto error; 
  59.         
  60.     penumvariant->m_cRef = 0;
  61.     
  62.     // Copy elements into safe array that is used in enumerator implemenatation and 
  63.     // initialize state of enumerator.
  64.     hr = SafeArrayGetLBound(psa, 1, &lLBound);
  65.     if (FAILED(hr))
  66.         goto error;
  67.     penumvariant->m_cElements = cElements;    
  68.     penumvariant->m_lLBound = lLBound;
  69.     penumvariant->m_lCurrent = lLBound;                  
  70.     hr = SafeArrayCopy(psa, &penumvariant->m_psa);
  71.     if (FAILED(hr))
  72.        goto error;
  73.     
  74.     *ppenumvariant = penumvariant;
  75.     return NOERROR;
  76.     
  77. error: 
  78.     if (penumvariant == NULL)
  79.         return E_OUTOFMEMORY;   
  80.                               
  81.     if (penumvariant->m_psa) 
  82.         SafeArrayDestroy(penumvariant->m_psa);   
  83.     penumvariant->m_psa = NULL;     
  84.     delete penumvariant;
  85.     return hr;
  86. }
  87.  
  88. /*
  89.  * CEnumVariant::CEnumVariant
  90.  *
  91.  * Purpose:
  92.  *  Constructor for CEnumVariant object. Initializes members to NULL.
  93.  *
  94.  */
  95. CEnumVariant::CEnumVariant()
  96. {    
  97.     m_psa = NULL;
  98. }
  99.  
  100. /*
  101.  * CEnumVariant::~CEnumVariant
  102.  *
  103.  * Purpose:
  104.  *  Destructor for CEnumVariant object. 
  105.  *
  106.  */
  107. CEnumVariant::~CEnumVariant()
  108. {                   
  109.     if (m_psa) SafeArrayDestroy(m_psa);
  110. }
  111.  
  112. /*
  113.  * CEnumVariant::QueryInterface, AddRef, Release
  114.  *
  115.  * Purpose:
  116.  *  Implements IUnknown::QueryInterface, AddRef, Release
  117.  *
  118.  */
  119. STDMETHODIMP
  120. CEnumVariant::QueryInterface(REFIID iid, void FAR* FAR* ppv) 
  121. {   
  122.     *ppv = NULL;
  123.         
  124.     if (iid == IID_IUnknown || iid == IID_IEnumVARIANT) 
  125.         *ppv = this;     
  126.     else return E_NOINTERFACE; 
  127.  
  128.     AddRef();
  129.     return NOERROR;    
  130. }
  131.  
  132.  
  133. STDMETHODIMP_(ULONG)
  134. CEnumVariant::AddRef(void)
  135. {
  136.  
  137. #ifdef _DEBUG   
  138.     TCHAR ach[50];
  139.     wsprintf(ach, TEXT("Ref = %ld, Enum\r\n"), m_cRef+1); 
  140.     OutputDebugString(ach); 
  141. #endif  
  142.     
  143.     return ++m_cRef;  // AddRef Application Object if enumerator will outlive application object
  144. }
  145.  
  146.  
  147. STDMETHODIMP_(ULONG)
  148. CEnumVariant::Release(void)
  149. {
  150.  
  151. #ifdef _DEBUG   
  152.     TCHAR ach[50];
  153.     wsprintf(ach, TEXT("Ref = %ld, Enum\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.  * CEnumVariant::Next
  167.  *
  168.  * Purpose:
  169.  *  Retrieves the next cElements elements. Implements IEnumVARIANT::Next. 
  170.  *
  171.  */
  172. STDMETHODIMP
  173. CEnumVariant::Next(ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched)
  174.     HRESULT hr;
  175.     ULONG l;
  176.     long l1;
  177.     ULONG l2;
  178.     
  179.     if (pcElementFetched != NULL)
  180.         *pcElementFetched = 0;
  181.         
  182.     // Retrieve the next cElements elements.
  183.     for (l1=m_lCurrent, l2=0; l1<(long)(m_lLBound+m_cElements) && l2<cElements; l1++, l2++)
  184.     {
  185.        hr = SafeArrayGetElement(m_psa, &l1, &pvar[l2]); 
  186.        if (FAILED(hr))
  187.            goto error; 
  188.     }
  189.     // Set count of elements retrieved
  190.     if (pcElementFetched != NULL)
  191.         *pcElementFetched = l2;
  192.     m_lCurrent = l1;
  193.     
  194.     return  (l2 < cElements) ? S_FALSE : NOERROR;
  195.  
  196. error:
  197.     for (l=0; l<cElements; l++)
  198.         VariantClear(&pvar[l]);
  199.     return hr;    
  200. }
  201.  
  202. /*
  203.  * CEnumVariant::Skip
  204.  *
  205.  * Purpose:
  206.  *  Skips the next cElements elements. Implements IEnumVARIANT::Skip. 
  207.  *
  208.  */
  209. STDMETHODIMP
  210. CEnumVariant::Skip(ULONG cElements)
  211. {   
  212.     m_lCurrent += cElements; 
  213.     if (m_lCurrent > (long)(m_lLBound+m_cElements))
  214.     {
  215.         m_lCurrent =  m_lLBound+m_cElements;
  216.         return S_FALSE;
  217.     } 
  218.     else return NOERROR;
  219. }
  220.  
  221. /*
  222.  * CEnumVariant::Reset
  223.  *
  224.  * Purpose:
  225.  *  Resets the current element in the enumerator to the beginning. Implements IEnumVARIANT::Reset. 
  226.  *
  227.  */
  228. STDMETHODIMP
  229. CEnumVariant::Reset()
  230.     m_lCurrent = m_lLBound;
  231.     return NOERROR;
  232. }
  233.  
  234. /*
  235.  * CEnumVariant::Clone
  236.  *
  237.  * Purpose:
  238.  *  Creates a copy of the current enumeration state. Implements IEnumVARIANT::Clone. 
  239.  *
  240.  */
  241. STDMETHODIMP
  242. CEnumVariant::Clone(IEnumVARIANT FAR* FAR* ppenum)
  243. {
  244.     CEnumVariant FAR* penum = NULL;
  245.     HRESULT hr;
  246.     
  247.     *ppenum = NULL;
  248.     
  249.     hr = CEnumVariant::Create(m_psa, m_cElements, &penum);
  250.     if (FAILED(hr))
  251.         goto error;        
  252.     penum->AddRef();
  253.     penum->m_lCurrent = m_lCurrent; 
  254.     
  255.     *ppenum = penum;        
  256.     return NOERROR;
  257.      
  258. error:
  259.     if (penum)
  260.         penum->Release();
  261.     return hr;        
  262. }
  263.