ENUMVAR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:6k
源码类别:

Windows编程

开发平台:

Visual C++

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