本文给出了在ATL环境下创建对象型的方法,适用于VC6、VC8
首先,设定集合类为XCollection,子对象为XItem。
第一步:添加一个ATL Simple Objecct,起名为XItem。
第二步:修改IDL文件,添加IXCollection接口。接口声明如下:
interface IXItem; //向前声明
[
object,
uuid(4807AD05-1CCF-4CFF-A134-8CB12AEA1655),
dual,
helpstring("IXCollection Interface"),
pointer_default(unique)
]
interface IXCollection : IDispatch
{
[id(1), helpstring("method Add")] HRESULT Add([out,retval] IXItem** ppVal);
[id(2), helpstring("method Remove")] HRESULT Remove([in] long i, [out,retval] IXItem** ppVal);
[propget] HRESULT Count([out, retval] long* pnCount);
[id(DISPID_VALUE), propget, helpstring("property Item (1-based)")] HRESULT Item([in] long i, [out, retval] IXItem** ppItem);
[id(DISPID_NEWENUM), propget] HRESULT _NewEnum([out, retval] IUnknown** ppEnum);
};
......
......
[
uuid(DF7F1C9F-ED81-41E3-8796-13A559B1DE0F),
helpstring("XCollection Class"),
noncreatable,
]
coclass XCollection
{
[default] interface IXCollection;
};
第三步:添加XCollection.h文件。文件如下:
#ifndef __XCOLLECTION_H_
#define __XCOLLECTION_H_
#include "resource.h" // main symbols
#include "cltnadaptors.h"
#include <vector> //本例用vector实现
#include "XItem.h"
using namespace std;
typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
_CopyVariantFromAdaptItf<IXItem>,
vector < CAdapt< CComPtr<IXItem> > > >
CComEnumVariantOnSTL;
typedef ICollectionOnSTLImpl<IDispatchImpl<IXCollection, &IID_IXCollection>,
vector< CAdapt< CComPtr<IXItem> > >,
IXItem*,
_CopyItfFromAdaptItf<IXItem>,
CComEnumVariantOnSTL>
IXCollectionImpl;
// CXCollection
class ATL_NO_VTABLE CXCollection :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CXCollection, &CLSID_XCollection>,
public IXCollectionImpl
{
public:
CXCollection()
{
}
DECLARE_NO_REGISTRY()
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CXCollection)
COM_INTERFACE_ENTRY(IXCollection)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
// IXCollection
public:
STDMETHOD(Add)(IXItem** ppVal)
{
HRESULT hr = CXItem::CreateInstance(ppVal);
if(SUCCEEDED(hr))
{
CComPtr<IXItem> spXItem = *ppVal;
m_coll.push_back(spXItem );
}
return hr;
}
STDMETHOD(Remove)(long Index, ** ppVal)
{
return S_OK;
}
};
#endif //__XCOLLECTION_H_
第四步:添加头文件cltnadaptors.h,cltnadaptors.h代码如下:
#ifndef _CLTNADAPTORS_H
#define _CLTNADAPTORS_H
template <typename T>
struct _CopyVariantFromAdaptItf {
static HRESULT copy(VARIANT* p1, const CAdapt< CComPtr<T> >* p2) {
HRESULT hr = p2->m_T->QueryInterface(IID_IDispatch, (void**)&p1->pdispVal);
if( SUCCEEDED(hr) ) {
p1->vt = VT_DISPATCH;
}
else {
hr = p2->m_T->QueryInterface(IID_IUnknown, (void**)&p1->punkVal);
if( SUCCEEDED(hr) ) {
p1->vt = VT_UNKNOWN;
}
}
return hr;
}
static void init(VARIANT* p) { VariantInit(p); }
static void destroy(VARIANT* p) { VariantClear(p); }
};
template <typename T>
struct _CopyItfFromAdaptItf {
static HRESULT copy(T** p1, const CAdapt< CComPtr<T> >* p2) {
if( *p1 = p2->m_T ) return (*p1)->AddRef(), S_OK;
return E_POINTER;
}
static void init(T** p) {}
static void destroy(T** p) { if( *p ) (*p)->Release(); }
};
#endif