很久不用ATL和STL,写起代码来慢多了:),下面把基本原理和如何使用写在下面。(http://blog.youkuaiyun.com/kql01)
基本原理:
Next()函数和STL容器通过迭代子遍历operator++()类似,所以只需要循环调用operator++操作就可以很容易实现Next()函数。将容器中元素赋值给Next提供的元素数组,则可能需要一个转换过程,可以通过自己定义一个辅助函数copy()来完成转换,ATL中定义了一个模板类实现枚举类型的初始化、销毁和拷贝操作,如下:
template <class EnumT, class ContainT>
class _Copy
{
public:
static HRESULT copy(EnumT * p1, ContainT * p2) {} // 拷贝容器中的元素到枚举缓冲区中
static void init(EnumT *) {} // 初始化该类型的数据
static void destroy(EnumT *) {} // 销毁新生成的枚举元素
};
Skip()函数类Next()函数。
容器需要支持的接口:
提供迭代子类型iteraotr的定义,并支持begin()和end()两个函数。
因此基本上标准的STL容器均支持。
如何使用:
定义枚举类型:
template <class Base, const IID* piid, class T, class Copy, class CollType, class ThreadModel = CComObjectThreadModel> class ATL_NO_VTABLE CComEnumOnSTL
这里需要注意的是Copy类的实现,一般使用typedef来定义,简洁可读性高。
初始化
HRESULT Init(IUnknown *pUnkForRelease, CollType& collection)
pUnkForRelease:保持对外部接口引用,避免提早释放。
Collection:提供枚举的容器。
使用范例:
在实际的应用中常常需要实现IEnmuString接口,下面是接口的一个实现:
首先确定容器类型,这里假设为vector<CString>类型,枚举器的类型定义:
typedef CComEnumOnSTL< IEnumString, &IID_IEnumString, LPOLESTR,_CopyOLESTRFromCString, vector<CString> > CEnumStringOnVector;
然后定义拷贝函数,如下:
struct _CopyOLESTRFromCString
{
static HRESULT copy(LPOLESTR* p1, CString* p2 )
{
*p1 = (LPOLESTR)CoTaskMemAlloc( (p2->GetLength() + 1) * sizeof(OLECHAR) );
if( *p1 )
{
USES_CONVERSION;
ocscpy( *p1, CT2OLE( (LPCTSTR)(*p2) ) );
return S_OK;
}
return E_OUTOFMEMORY;
}
static void init( LPOLESTR* p1) {}
static void destroy( LPOLESTR* p1) { CoTaskMemFree( *p1 ); }
};
最后使用:
CComObject< CEnumStringOnVector >* pe = NULL;
HRESULT hr = CComObject< CEnumStringOnVector >::CreateInstance( &pe );
if( SUCCEEDED( hr ) ){
pe->AddRef();
pe->Init( NULL, vecFiles );
pe->Release();
}
Enjoy!