组件对象模型与ATL实现
2010-09-04 20:48:02 来源:WEB开发网三 实现集合对象
下面增加具体的实现代码,以把Layers和Shapes变成集合类(Collection)。
第一步 把下面的代码添加到stdafx.h中
// stdafx.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(); }
};
第二步 把Layers变成集合对象
把下面的代码添加到Layers.h中,添加后的Layers.h为:
// Layers.h : CLayers 的声明
#pragma once
#include "resource.h" // 主符号
#include "MapLib.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全DCOM 支持的Windows Mobile 平台)上无法正确支持单线程COM 对象。定义_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制ATL 支持创建单线程COM 对象实现并允许使用其单线程COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非DCOM Windows CE 平台支持的唯一线程模型。"
#endif
// 下面加粗的文字是我添加的代码
#include "Layer.h"
typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
_CopyVariantFromAdaptItf<ILayer>,
list< CAdapt< CComPtr<ILayer> > > >
CComEnumVariantOnListOfLayers;
typedef ICollectionOnSTLImpl<IDispatchImpl<ILayers, &IID_ILayers>,
list< CAdapt< CComPtr<ILayer> > >,
ILayer*,
_CopyItfFromAdaptItf<ILayer>,
CComEnumVariantOnListOfLayers>
ILayerCollImpl;
// CLayers
class ATL_NO_VTABLE CLayers :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CLayers>, // non-createable,去掉注册表项
public ISupportErrorInfo,
public ILayerCollImpl
{
public:
CLayers()
{
}
//DECLARE_REGISTRY_RESOURCEID(IDR_LAYERS)
DECLARE_NO_REGISTRY() // non-createable,去掉注册表项
// 原来的代码被我注释掉
// CHEUNGMINE:
// CHEUNGMINE: // CLayers
// CHEUNGMINE: class ATL_NO_VTABLE CLayers :
// CHEUNGMINE: public CComObjectRootEx<CComSingleThreadModel>,
// CHEUNGMINE: public CComCoClass<CLayers, &CLSID_Layers>,
// CHEUNGMINE: public ISupportErrorInfo,
// CHEUNGMINE: public IDispatchImpl<ILayers, &IID_ILayers, &LIBID_MapLibLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
// CHEUNGMINE: {
// CHEUNGMINE: public:
// CHEUNGMINE: CLayers()
// CHEUNGMINE: {
// CHEUNGMINE: }
// CHEUNGMINE: DECLARE_REGISTRY_RESOURCEID(IDR_LAYERS)
BEGIN_COM_MAP(CLayers)
COM_INTERFACE_ENTRY(ILayers)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
};
OBJECT_ENTRY_AUTO(__uuidof(Layers), CLayers)
然后编译,出现一堆的错误。首先在文件“stdafx.h”中的适当位置加入使用STL的语句,如下:
// Standard C++ STL supports
#include <stack>
#include <vector>
#include <list>
#include <map>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
然后,重新编译,全部OK。接下来,修改“MapLib.idl”文件的ILayers部分,使其如下所示:
interface ILayers : IDispatch{
[propget,helpstring("Layer元素数目")] HRESULT Count([out,retval] long *nItems);
[id(DISPID_VALUE),propget,helpstring("取得指定索引的Layer元素。索引以为基数")]
HRESULT Item([in] long index, [out,retval] ILayer** ppRef);
[id(DISPID_NEWENUM),propget,hidden] HRESULT _NewEnum([out,retval] IUnknown** ppEnum);
// [id(1),helpstring("向集合增加一个元素,返回引用")] HRESULT Add([out,retval] ILayer** ppRef);
};
更多精彩
赞助商链接