//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000 // // File: enumerator.h // // Contents: Supports enumeration for collections of com objects // // History: 14-Oct-99 VivekJ Created (as comerror.h) // 08-Mar-2000 AudriusZ separated some code into enumerator.h file // //-------------------------------------------------------------------------- #ifndef ENUMERATOR_H_INCLUDED #define ENUMERATOR_H_INCLUDED #pragma once /***************************************************************************\ * * CLASS: CMMCNewEnumImpl * * PURPOSE: Implements enumeration for collection class * EnumImplementor class is responsible for implementing these methods: * SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch); * SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, _Position &pos); * SC ScEnumReset(_Position &pos); * \***************************************************************************/ /****** usage tips ******************************************************* * Generally you will provide just 2 params to template - this means * the tied object of your base class needs to implement following methods: * ScEnumNext, ScEnumSkip, ScEnumReset; * * If you pass same class as the first and the third template parameter, your base class is * required to implement mentioned methods (not the tied object). * It's usefull when you want to have collection and enueration in one class. * * You also may specify any other class implementing the methods as the 3rd parameter, * but then the BaseClass needs to implement method 'ScGetEnumImplementor' returning * the instance of that class * * NOTE1: since it's template class, the BaseClass is not required to define/implement * ScGetTiedObject, when it implements enum methods itself. * NOTE2: But it always IS REQUIRED to define CMyTiedObject type to compile. * (this template class needs it to be anything different than the BaseClass) * It is suggested to typedef it as void : "typedef void CMyTiedObject;" * NOTE3: Make sure CMyTiedObject type is public or protected ************************************************************************/ template class CMMCNewEnumImpl : public BaseClass { // Methods to get proper implementor for Enum methods // simple one when implemented by the base class SC ScGetEnumImplementor(BaseClass * &pObj) { pObj = this; return SC(S_OK); } // when implemented by the tied object (default) - also simple SC ScGetEnumImplementor(BaseClass::CMyTiedObject * &pObj) { return ScGetTiedObject(pObj); } public: STDMETHOD(get__NewEnum)(IUnknown** ppUnk); }; /*+-------------------------------------------------------------------------* * class CMMCEnumerator * * * PURPOSE: General purpose enumerator class. Keyed to a position object, * which is templated. * * The following three methods need to be implemented by the tied object: * * SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch); // should return the next element. * SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, * _Position &pos); * SC ScEnumReset(_Position &pos); * * Cloning the enumerator is taken care of automatically. * * NOTE: The Position object must have a copy constructor and assignment * operator. *+-------------------------------------------------------------------------*/ typedef IEnumVARIANT ** PPENUMVARIANT; typedef VARIANT * PVARIANT; template class CMMCEnumerator : public IEnumVARIANT, public IMMCSupportErrorInfoImpl<&IID_IEnumVARIANT, &GUID_NULL>, // rich error handling public CComObjectRoot, public CTiedComObject { typedef CMMCEnumerator ThisClass; typedef TiedObj CMyTiedObject; friend TiedObj; public: BEGIN_COM_MAP(ThisClass) COM_INTERFACE_ENTRY(IEnumVARIANT) END_COM_MAP() DECLARE_NOT_AGGREGATABLE(ThisClass) // Returns the next celt items starting from the current position // in the array rgvar STDMETHODIMP Next(unsigned long celt, PVARIANT rgvar, unsigned long * pceltFetched); // Skips over the next celt elements in the enumeration sequence. STDMETHODIMP Skip(unsigned long celt); // Resets the enumeration sequence to the beginning STDMETHODIMP Reset(); // Creates a copy of the current state of enumeration STDMETHODIMP Clone(PPENUMVARIANT ppenum); public: // the position object that keeps track of the present location. _Position m_position; }; /*+-------------------------------------------------------------------------* * class CMMCArrayEnumBase * * PURPOSE: General purpose array enumeration base class. * Particularly useful when array of items to be enumerated is initially * available, or when com object creation is not a big penalty and there * is no need to postpone item creation to when they are requested. * * USAGE: typedef your enumerator as CMMCNewEnumImpl parameterized by this class * - or even better - create the instance of CMMCArrayEnum class. * Use Init method passing an array of pointers to items [first, last) *+-------------------------------------------------------------------------*/ template class CMMCArrayEnumBase : public CMMCIDispatchImpl<_CollectionInterface>, public CTiedObject // enumerators are tied to it { protected: typedef void CMyTiedObject; // not tied public: BEGIN_MMC_COM_MAP(CMMCArrayEnumBase) END_MMC_COM_MAP() public: // Returns count of items in the collection STDMETHODIMP get_Count( PLONG pCount ); // Returns specified item from collection STDMETHODIMP Item( long Index, _ItemInterface ** ppItem ); // Resets position to the first item in the collection ::SC ScEnumReset (unsigned &pos); // Returns item from the collection, advances position ::SC ScEnumNext (unsigned &pos, PDISPATCH & pDispatch); // Skips the amount of items in enumeration ::SC ScEnumSkip (unsigned long celt, unsigned long& celtSkipped, unsigned &pos); // Initializes the array with given iterators template void Init(InIt first, InIt last) { m_array.clear(); m_array.reserve(last - first); while(first != last) m_array.push_back(*first), ++first; } private: // data members std::vector< CComPtr<_ItemInterface> > m_array; }; /*+-------------------------------------------------------------------------* * class CMMCArrayEnumBase * * PURPOSE: General purpose array enumeration class. * Particularly useful when array of items to be enumerated is initially * available, or when com object creation is not a big penalty and there * is no need to postpone item creation to when they are requested. * * USAGE: create the instance of CMMCArrayEnum class whenever you need an * enumerator for the array of objects you have. * Parameterized by collection type and element type; * For instance CMMCArrayEnum< Nodes, Node > * Use Init method passing an array of pointers to items [first, last) * * EXAMPLE: << skipping error checking for clarity >> * void GetNodes(std::vector& InNodes, PPNODES ppOutNodes) * { * typedef CComObject< CMMCArrayEnum > EnumNodes; * EnumNodes *pNodes = NULL; * EnumNodes::CreateInstance(&pNodes); // create * pNodes->Init(InNodes.begin(), InNodes.end()); // initialize with array * pNodes->AddRef(); // addref for caller * *ppOutNodes = pNodes; // return * } * *+-------------------------------------------------------------------------*/ template class CMMCArrayEnum : public CMMCNewEnumImpl, unsigned, CMMCArrayEnumBase<_CollT, _ItemT> > { }; // include inline definitions #include "enumerator.inl" #endif // ENUMERATOR_H_INCLUDED