首页 > 代码库 > 一个使用MFC实现Com聚合的例子
一个使用MFC实现Com聚合的例子
在网上搜Com聚合的例子,发现都比较少,要么是使用ATL,要么是模拟ATL的方式,要么就是模拟MFC的方式,大多偏于原理性的介绍。由于模拟MFC 和真正使用MFC时,在查询IUnknown接口时,流程上有所不同,所以模拟MFC的方式与直接从CCmdTarget派生时,在流程上有较大的差别。即使懂了Com聚合的原理,也可能无法直接使用MFC实现Com 聚合,本人经过一番摸索,终于实现了直接使用MFC实现COM聚合,例子如下:
1.被聚合的组件
1.1 接口声明
#pragma once typedef long HRESULT; // {30DF3430-0266-11cf-BAA6-00AA003E0EED} extern const GUID CLSID_Math; //{ 0x30df3430, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } }; ////////////////////////////////////////////////////////////////////////////////////// // {30DF3432-0266-11cf-BAA6-00AA003E0EED} extern const GUID IID_IOPerator; //{ 0x30df3432, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } }; class IOPerator:public IUnknown { public: virtual HRESULT _stdcall Add(int nParam1, int nParam2, int* pResult) =0; virtual HRESULT _stdcall Subtract(int nParam1, int nParam2, int* pResult) =0; virtual HRESULT _stdcall Multiple(int nParam1, int nParam2, int* pResult) =0; virtual HRESULT _stdcall Divide(int nParam1, int nParam2, int* pResult) =0; }; // {30DF3433-0266-11cf-BAA6-00AA003E0EED} extern const GUID IID_IAdvanceOPerator; //{ 0x30df3433, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } }; class IAdvanceOPerator:public IUnknown { public: virtual HRESULT _stdcall Abs(int nParam1, int* pResult) =0; virtual HRESULT _stdcall Power(int nParam1, int nParam2, int* pResult) =0; };
// CMyMath command target class CMyMath : public CCmdTarget { DECLARE_DYNCREATE(CMyMath) public: CMyMath(); virtual ~CMyMath(); virtual void OnFinalRelease(); protected: DECLARE_OLECREATE(CMyMath) DECLARE_MESSAGE_MAP() DECLARE_DISPATCH_MAP() DECLARE_INTERFACE_MAP() BEGIN_INTERFACE_PART(OPerator, IOPerator) STDMETHOD_(HRESULT, Add)(int nParam1, int nParam2, int* pResult); STDMETHOD_(HRESULT, Subtract)(int nParam1, int nParam2, int* pResult); STDMETHOD_(HRESULT, Multiple)(int nParam1, int nParam2, int* pResult); STDMETHOD_(HRESULT, Divide)(int nParam1, int nParam2, int* pResult); END_INTERFACE_PART(OPerator) BEGIN_INTERFACE_PART(AdvanceOperator, IAdvanceOPerator) STDMETHOD_(HRESULT, Abs)(int nParam1, int* pResult); STDMETHOD_(HRESULT, Power)(int nParam1, int nParam2, int* pResult); END_INTERFACE_PART(AdvanceOperator) };
1.2 组件实现
#include "stdafx.h" #include "MyCom16.h" #include "MyMath.h" // CMyMath IMPLEMENT_DYNCREATE(CMyMath, CCmdTarget) CMyMath::CMyMath() { EnableAutomation(); EnableAggregation(); } CMyMath::~CMyMath() { } void CMyMath::OnFinalRelease() { // When the last reference for an automation object is released // OnFinalRelease is called. The base class will automatically // deletes the object. Add additional cleanup required for your // object before calling the base class. CCmdTarget::OnFinalRelease(); } BEGIN_MESSAGE_MAP(CMyMath, CCmdTarget) END_MESSAGE_MAP() BEGIN_DISPATCH_MAP(CMyMath, CCmdTarget) END_DISPATCH_MAP() // Note: we add support for IID_IMyMath to support typesafe binding // from VBA. This IID must match the GUID that is attached to the // dispinterface in the .IDL file. // {7259EA0F-0E64-4FF9-BBA1-332E82AFA0D3} static const IID IID_IMyMath = { 0x7259EA0F, 0xE64, 0x4FF9, { 0xBB, 0xA1, 0x33, 0x2E, 0x82, 0xAF, 0xA0, 0xD3 } }; static const GUID IID_IOPerator = { 0x30df3432, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed }}; static const GUID IID_IAdvanceOPerator = { 0x30df3433, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed }}; // CLSID_Math IMPLEMENT_OLECREATE(CMyMath, "MyCom16.MyMath", 0x30df3430, 0x266, 0x11cf, 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed) BEGIN_INTERFACE_MAP(CMyMath, CCmdTarget) INTERFACE_PART(CMyMath,IID_IMyMath, Dispatch) INTERFACE_PART(CMyMath,IID_IOPerator,OPerator) INTERFACE_PART(CMyMath,IID_IAdvanceOPerator,AdvanceOperator) END_INTERFACE_MAP() // CMyMath message handlers ULONG CMyMath::XOPerator::AddRef() { METHOD_PROLOGUE(CMyMath, OPerator); return pThis->ExternalAddRef(); } ULONG CMyMath::XOPerator::Release() { METHOD_PROLOGUE(CMyMath, OPerator); return pThis->ExternalRelease(); } HRESULT CMyMath::XOPerator::QueryInterface(REFIID riid, void** ppObject) { METHOD_PROLOGUE_EX_(CMyMath, OPerator); return pThis->ExternalQueryInterface((void *)&riid,ppObject); } HRESULT CMyMath::XOPerator::Add( int nParam1, int nParam2, int* pResult ) { *pResult = nParam1 + nParam2; return S_OK; } HRESULT CMyMath::XOPerator::Subtract( int nParam1, int nParam2, int* pResult ) { *pResult = nParam1 - nParam2; return S_OK; } HRESULT CMyMath::XOPerator::Multiple( int nParam1, int nParam2, int* pResult ) { *pResult = nParam1 * nParam2; return S_OK; } HRESULT CMyMath::XOPerator::Divide( int nParam1, int nParam2, int* pResult ) { *pResult = nParam1 / nParam2; return S_OK; } ULONG CMyMath::XAdvanceOperator::AddRef() { METHOD_PROLOGUE(CMyMath, AdvanceOperator); return pThis->ExternalAddRef(); } ULONG CMyMath::XAdvanceOperator::Release() { METHOD_PROLOGUE(CMyMath, AdvanceOperator); return pThis->ExternalRelease(); } HRESULT CMyMath::XAdvanceOperator::QueryInterface(REFIID riid, void** ppObject) { METHOD_PROLOGUE(CMyMath, AdvanceOperator); return pThis->ExternalQueryInterface((void *)&riid,ppObject); } HRESULT _stdcall CMyMath::XAdvanceOperator::Abs( int nParam1, int* pResult ) { if(nParam1 < 0) *pResult = -nParam1; else *pResult = nParam1; return S_OK; } HRESULT _stdcall CMyMath::XAdvanceOperator::Power( int nParam1, int nParam2, int* pResult ) { *pResult =1; for(int i=0;i<nParam2;i++) *pResult *=nParam1; return S_OK; }
2 聚合组件
2.1接口声明
#pragma once typedef long HRESULT; class IArea:public IUnknown { public: virtual HRESULT _stdcall Triangle(int width, int High, float* pResult) =0; virtual HRESULT _stdcall Square(int lengh, float* pResult) =0; virtual HRESULT _stdcall Cirle(int r, float* pResult) =0; };
#pragma once #include "IArea.h" // CMyMath2 command target class CMyMath2 : public CCmdTarget { DECLARE_DYNCREATE(CMyMath2) public: CMyMath2(); virtual ~CMyMath2(); virtual void OnFinalRelease(); virtual BOOL OnCreateAggregates(); BEGIN_INTERFACE_PART(Area, IArea) STDMETHOD_(HRESULT, Triangle)(int width, int High, float* pResult); STDMETHOD_(HRESULT, Square)(int lengh, float* pResult); STDMETHOD_(HRESULT, Cirle)(int r, float* pResult); END_INTERFACE_PART(Area) protected: DECLARE_OLECREATE(CMyMath2) DECLARE_MESSAGE_MAP() DECLARE_DISPATCH_MAP() DECLARE_INTERFACE_MAP() };
2.2 接口实现
#include "MyMath2.h" #include <iostream> using namespace std; const float PI = 3.14; static const GUID CLSID_Math = { 0x30df3430, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } }; // CMyMath2 IMPLEMENT_DYNCREATE(CMyMath2, CCmdTarget) CMyMath2::CMyMath2() { EnableAutomation(); } CMyMath2::~CMyMath2() { } void CMyMath2::OnFinalRelease() { // When the last reference for an automation object is released // OnFinalRelease is called. The base class will automatically // deletes the object. Add additional cleanup required for your // object before calling the base class. if(m_xInnerUnknown !=NULL) { IUnknown *pUnk =(IUnknown *)m_xInnerUnknown; pUnk->Release(); } CCmdTarget::OnFinalRelease(); } BEGIN_MESSAGE_MAP(CMyMath2, CCmdTarget) END_MESSAGE_MAP() BEGIN_DISPATCH_MAP(CMyMath2, CCmdTarget) END_DISPATCH_MAP() // Note: we add support for IID_IMyMath2 to support typesafe binding // from VBA. This IID must match the GUID that is attached to the // dispinterface in the .IDL file. // {60B1DE57-1DE8-4759-B220-C35E03B2049D} static const IID IID_IMyMath2 = { 0x60B1DE57, 0x1DE8, 0x4759, { 0xB2, 0x20, 0xC3, 0x5E, 0x3, 0xB2, 0x4, 0x9D } }; static const GUID IID_IArea = { 0x30df3452, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed }}; // CLSID_Math IMPLEMENT_OLECREATE(CMyMath2, "MyCom9.MyMath2", 0x30df3450, 0x266, 0x11cf, 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed) BEGIN_INTERFACE_MAP(CMyMath2, CCmdTarget) INTERFACE_PART(CMyMath2, IID_IMyMath2, Dispatch) INTERFACE_PART(CMyMath2,IID_IArea,Area) INTERFACE_AGGREGATE(CMyMath2,m_xInnerUnknown) //CMyMath2聚合了CMyMath END_INTERFACE_MAP() //CMyMath2聚合了CMyMath BOOL CMyMath2::OnCreateAggregates() { #if 0 //这里是关键,不能这样写 ::CoCreateInstance(CLSID_Math,(IUnknown *)this,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&m_xInnerUnknown); #else LPUNKNOWN pUnk = GetControllingUnknown(); ::CoCreateInstance(CLSID_Math,(IUnknown *)pUnk,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&m_xInnerUnknown); #endif return TRUE; } // CMyMath2 message handlers HRESULT _stdcall CMyMath2::XArea::Triangle( int width, int High, float* pResult ) { *pResult =width*High *1.0/2; return S_OK; } HRESULT _stdcall CMyMath2::XArea::Square( int lengh, float* pResult ) { *pResult =lengh *lengh*1.0/2; return S_OK; } HRESULT _stdcall CMyMath2::XArea::Cirle( int r, float* pResult ) { *pResult = PI *r*r; return S_OK; } ULONG CMyMath2::XArea::AddRef() { METHOD_PROLOGUE(CMyMath2, Area); return pThis->ExternalAddRef(); } ULONG CMyMath2::XArea::Release() { METHOD_PROLOGUE(CMyMath2, Area); return pThis->ExternalRelease(); } HRESULT CMyMath2::XArea::QueryInterface(REFIID riid, void** ppObject) { METHOD_PROLOGUE_EX_(CMyMath2, Area); return pThis->ExternalQueryInterface((void *)&riid,ppObject);; }
3.测试代码
#include "../MyCom16/Operator.h"
#include "../MyCom9/IArea.h"
using namespace std;
static const GUID CLSID_Math =
{ 0x30df3430, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } };
static const GUID IID_IOPerator =
{ 0x30df3432, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } };
static const GUID IID_IAdvanceOPerator =
{ 0x30df3433, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed } };
static const GUID CLSID_Math2 =
{ 0x30df3450, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed }};
static const GUID IID_IArea =
{ 0x30df3452, 0x266, 0x11cf, { 0xba, 0xa6, 0x0, 0xaa, 0x0, 0x3e, 0xe, 0xed }};
int _tmain(int argc, _TCHAR* argv[])
{
CLSID clsId;
IClassFactory *pMathFactory = NULL;
IUnknown* pUnknown = NULL;
IUnknown* pUnk = NULL;
IOPerator *pOPerator = NULL;
IAdvanceOPerator *pAdvanceOperator = NULL;
IArea *pArea = NULL;
IArea *pArea2 = NULL;
IAdvanceOPerator *pAdvanceOperator2 = NULL;
int nResult = 0;
HRESULT hRes;
CoInitialize(NULL);
///////////////////////Test MyCom1///////////////////////////////////////////////////////////////////
#if 1
//CLSIDFromProgID(_T("Testcom1 Server"),&clsId);
hRes = CoGetClassObject(CLSID_Math, CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pMathFactory);
if(FAILED(hRes))
{
return 0;
}
pMathFactory->CreateInstance(NULL,IID_IOPerator,(void **)&pOPerator);
pMathFactory->Release();
pOPerator->Add(5,6,&nResult);
cout<<"5+6 ="<<nResult<<endl;
pOPerator->Multiple(5,6,&nResult);
cout<<"5*6 ="<<nResult<<endl;
pOPerator->Divide(5,6,&nResult);
cout<<"5/6 ="<<nResult<<endl;
pOPerator->QueryInterface(IID_IAdvanceOPerator,(void **)&pAdvanceOperator);
pAdvanceOperator->Abs(-123,&nResult);
cout<<"Abs(-123) ="<<nResult<<endl;
pAdvanceOperator->Power(5,3,&nResult);
cout<<"Power(5,3) ="<<nResult<<endl;
pAdvanceOperator->QueryInterface(IID_IUnknown,(void **)&pUnknown);
pOPerator->QueryInterface(IID_IUnknown,(void **)&pUnk);
pUnk->QueryInterface(IID_IAdvanceOPerator,(void **)&pAdvanceOperator2);
if(pUnk == pUnknown)
cout<<"They are the same com obj"<<endl;
else
cout<<"They not equal obj" <<endl;
pUnknown->Release();
pUnk->Release();
pAdvanceOperator->Release();
pOPerator->Release();
pAdvanceOperator2->Release();
pOPerator = NULL;
pAdvanceOperator = NULL;
pUnk = NULL;
pUnknown = NULL;
pAdvanceOperator2 =NULL;
#endif
/*
对聚合进行测试
Com9 聚合了Com1
*/
#if 1
pOPerator = NULL;
pAdvanceOperator = NULL;
pUnk =NULL;
pUnknown = NULL;
//CLSIDFromProgID(_T("Testcom1 Server"),&clsId);
hRes = CoGetClassObject(CLSID_Math2, CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pMathFactory);
if(FAILED(hRes))
{
return 0;
}
pMathFactory->CreateInstance(NULL,IID_IArea,(void **)&pArea);
pMathFactory->Release();
float fResult =0.0f;
pArea->Triangle(3,4,&fResult);
cout<<"Triangle(3,4) = "<<fResult<<endl;
pArea->Cirle(5,&fResult);
cout<<"Cirle(5) = "<<fResult<<endl;
pArea->QueryInterface(IID_IOPerator,(void **)&pOPerator);
pOPerator->Add(5,6,&nResult);
cout<<"5+6 ="<<nResult<<endl;
pOPerator->Multiple(5,6,&nResult);
cout<<"5*6 ="<<nResult<<endl;
pOPerator->Divide(5,6,&nResult);
cout<<"5/6 ="<<nResult<<endl;
pOPerator->QueryInterface(IID_IAdvanceOPerator,(void **)&pAdvanceOperator);
pAdvanceOperator->QueryInterface(IID_IArea,(void **)&pArea2);
if(pArea == pArea2)
cout<<"They are the same com obj"<<endl;
else
cout<<"They not equal obj" <<endl;
pArea->QueryInterface(IID_IUnknown,(void **)&pUnknown);
pOPerator->QueryInterface(IID_IUnknown,(void **)&pUnk);
if(pUnk ==pUnknown)
cout<<"They are the same com obj"<<endl;
else
cout<<"They not equal obj" <<endl;
pUnknown->Release();
pUnk->Release();
pArea->Release();
pOPerator->Release();
pAdvanceOperator->Release();
pArea2->Release();
#endif
::CoUninitialize();
return 0;
}
一个使用MFC实现Com聚合的例子
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。