COM 对象模型

Scroll Down

stdafx.h中添加

#include <stack>
#include <vector>
#include <list>
#include <map>
#include <string>
#include <algorithm>
#include <functional>
using namespace ATL;
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(); }
};

Documents集合类

修改之前的代码:

// Documents.h : CDocuments 的声明

#pragma once
#include "resource.h"       // 主符号



#include "Interface_i.h"
#include "_IDocumentsEvents_CP.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

using namespace ATL;


// CDocuments

class ATL_NO_VTABLE CDocuments :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CDocuments, &CLSID_Documents>,
	public IConnectionPointContainerImpl<CDocuments>,
	public CProxy_IVPGDocumentsEvents<CDocuments>,
	public IDispatchImpl<IDocuments, &IID_IDocuments, &LIBID_InterfaceLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
	CDocuments()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_DOCUMENTS)


BEGIN_COM_MAP(CDocuments)
	COM_INTERFACE_ENTRY(IDocuments)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CDocuments)
	CONNECTION_POINT_ENTRY(__uuidof(_IDocumentsEvents))
END_CONNECTION_POINT_MAP()


	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

public:



};

OBJECT_ENTRY_AUTO(__uuidof(Documents), CDocuments)

修改之后的代码:

// Documents.h : CDocuments 的声明

#pragma once
#include "resource.h"       // 主符号



#include "Interface_i.h"
#include "_IDocumentsEvents_CP.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

using namespace ATL;
#include "Document.h"
typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
	_CopyVariantFromAdaptItf<IDocument>,
	std::list< CAdapt< CComPtr<IDocument> > > >
	CComEnumVariantOnListOfLayers;
typedef ICollectionOnSTLImpl<IDispatchImpl<IDocuments, &IID_IVPGDocuments>,
	std::list< CAdapt< CComPtr<IDocument> > >,
	IDocument*,
	_CopyItfFromAdaptItf<IDocument>,
	CComEnumVariantOnListOfLayers>
	IVPGDocumentCollImpl;

// CDocuments

class ATL_NO_VTABLE CDocuments :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CDocuments>,// non-createable,去掉注册表项
	public IConnectionPointContainerImpl<CDocuments>,
	public CProxy_IVPGDocumentsEvents<CDocuments>,
	public IDocumentCollImpl
{
public:
	CDocuments()
	{
	}

	//DECLARE_REGISTRY_RESOURCEID(IDR_DOCUMENTS)
	DECLARE_NO_REGISTRY() // non-createable,去掉注册表项

	BEGIN_COM_MAP(CDocuments)
		COM_INTERFACE_ENTRY(IDocuments)
		COM_INTERFACE_ENTRY(IDispatch)
		COM_INTERFACE_ENTRY(IConnectionPointContainer)
	END_COM_MAP()

	BEGIN_CONNECTION_POINT_MAP(CDocuments)
		CONNECTION_POINT_ENTRY(__uuidof(_IDocumentsEvents))
	END_CONNECTION_POINT_MAP()


	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}
	STDMETHODIMP Add(IDocument** ppRef)
	{
		CComPtr<IDocument> spObj;
		HRESULT hr = CDocument::CreateInstance(&spObj);
		if (SUCCEEDED(hr))
		{
			m_coll.push_back(spObj);
			return spObj.CopyTo(ppRef);
		}
		return hr;
	}
public:



};

OBJECT_ENTRY_AUTO(__uuidof(Documents), CDocuments)

主对象

#pragma once
#include "resource.h"       // 主符号



#include "Interface_i.h"
#include "_IPrintAppEvents_CP.h"
#include "Documents.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

using namespace ATL;


// CPrintApp

class ATL_NO_VTABLE CPrintApp :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CPrintApp, &CLSID_PrintApp>,
	public IConnectionPointContainerImpl<CPrintApp>,
	public CProxy_IPrintAppEvents<CPrintApp>,
	public IDispatchImpl<IPrintApp, &IID_IPrintApp, &LIBID_InterfaceLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
	CPrintApp()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_PRINTAPP)


BEGIN_COM_MAP(CPrintApp)
	COM_INTERFACE_ENTRY(IPrintApp)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CPrintApp)
	CONNECTION_POINT_ENTRY(__uuidof(_IPrintAppEvents))
END_CONNECTION_POINT_MAP()


	DECLARE_PROTECT_FINAL_CONSTRUCT()

	//创建文档集合实例
	HRESULT FinalConstruct()
	{
		return CDocuments::CreateInstance(&m_spDocuments);
	}

	void FinalRelease()
	{
	}
public:
	STDMETHOD(get_documents)(IDocuments** pVal){
		return m_spDocuments.CopyTo(pVal);
	}
private:
	CComPtr<IDocuments> m_spDocuments;
};

OBJECT_ENTRY_AUTO(__uuidof(PrintApp), CPrintApp)

IDL

// Interface.idl : Interface 的 IDL 源
//

// 此文件将由 MIDL 工具处理以
// 产生类型库(Interface.tlb)和封送处理代码。

import "oaidl.idl";
import "ocidl.idl";

[
	uuid(F47F1B67-6663-4FD3-BAEB-7C1910306967),
	version(1.0),
]
library InterfaceLib
{
	importlib("stdole2.tlb");
	[
		uuid(664C99AE-6A00-463A-870D-BAD7634909D6)
	]
	dispinterface _IDocumentEvents
	{
	properties:
	methods:
	};
	[
		object,
		uuid(092819D0-A0B1-4D83-AEA6-6AFD337B21E4),
		dual,
		nonextensible,
		pointer_default(unique)
	]
	interface IDocument : IDispatch{
	};
	[
		uuid(DD374567-6553-4B73-A81D-FD444185F70C)
	]
	coclass Document
	{
		[default] interface IDocument;
		[default, source] dispinterface _IDocumentEvents;
	};
	[
		uuid(EE5DF8C0-BE58-46D7-BC15-6DDFCB89532A)
	]
	dispinterface _IDocumentsEvents
	{
	properties:
	methods:
	};
	[
		object,
		uuid(263A7E38-4EDF-4EBF-BDDE-45928BDC940E),
		dual,
		nonextensible,
		pointer_default(unique)
	]
	interface IDocuments : IDispatch{
		[propget, helpstring("Documents元素数目")] HRESULT Count([out, retval] long *nItems);
		[id(DISPID_VALUE), propget, helpstring("取得指定索引的VPGDocuments元素。索引以为基数")]
		HRESULT Item([in] long index, [out, retval] IDocument** ppRef);
		[id(DISPID_NEWENUM), propget, hidden] HRESULT _NewEnum([out, retval] IUnknown** ppEnum);
		[id(1), helpstring("向集合增加一个元素,返回引用")] HRESULT Add([out, retval] IDocument** ppRef);
	};
	[
		uuid(AB4B2D1F-BCBE-4C5D-A3A7-7374AC67F7E6)
	]
	coclass Documents
	{
		[default] interface IDocuments;
		[default, source] dispinterface _IDocumentsEvents;
	};
	[
		uuid(935DBB5C-299B-4571-80F8-9B268C87D276)		
	]
	dispinterface _IPrintAppEvents
	{
		properties:
		methods:
	};
	[
		object,
		uuid(76ACE756-B8AD-4A50-A304-3BBEF3C10FF4),
		dual,
		nonextensible,
		pointer_default(unique)
	]
	interface IPrintApp : IDispatch{
		[propget, id(1)] HRESULT documents([out, retval] IDocuments** pVal);
	};
	[
		uuid(92AD4A0C-D25D-4AD2-81CC-52935573766B)
	]
	coclass PrintApp
	{
		[default] interface IJHPrintApp;
		[default, source] dispinterface _IPrintAppEvents;
	};
};

参考链接