一个用MFC实现Com聚合样本
ComATLATLMFCMFC MFCIUnknownMFCCCmdTargetComMFCCom MFCCOM
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) //CMyMath2CMyMath END_INTERFACE_MAP() //CMyMath2CMyMath 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;
}