import "oaidl.idl";
[
uuid(7FBB6A23-1425-11d2-8CAA-85047AB53E46),
object,
helpstring("Standard COM Interface")
]
interface ILoveCOM: IUnknown
{
HRESULT DevelopInterface(void);
HRESULT ThenDevelopImplementation(void);
}
[
uuid(7FBB6A25-1425-11d2-8CAA-85047AB53E46),
object,
helpstring("Another standard COM Interface")
]
interface IUseAnyTool: IUnknown
{
HRESULT UseCPP(void);
HRESULT UseMFC(void);
HRESULT UseATL(void);
HRESULT UseVB(void);
HRESULT UseJava(void);
}
[
uuid(7FBB6A26-1425-11d2-8CAA-85047AB53E46),
helpstring("Tao Of COM Library"),
version(1.0),
lcid(0)
]
library TaoOfCOMLib
{
importlib("stdole32.tlb");
[
uuid(7FBB6A27-1425-11d2-8CAA-85047AB53E46),
helpstring("The Tao Of COM")
]
coclass CoTaoOfCOM
{
interface IUnknown;
interface ILoveCOM;
interface IUseAnyTool;
}
}
Figure 2 A C++ COM Class
class CoTaoOfCPP : public ILoveCOM,
IUseAnyTool {
long m_cRef;
public:
CoTaoOfCPP();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// ILoveCOM
STDMETHODIMP DevelopInterface(void);
STDMETHODIMP ThenDevelopImplementation(void);
// IUseAnyTool
STDMETHODIMP UseCPP(void);
STDMETHODIMP UseMFC(void);
STDMETHODIMP UseATL(void);
STDMETHODIMP UseVB(void);
STDMETHODIMP UseJava(void);
};
Figure 3 Implementing IUnknown in C++
STDMETHODIMP CoTaoOfCPP::QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_ILoveCOM)
*ppv = static_cast<ILoveCOM*>(this);
else if (riid == IID_IUseAnyTool)
*ppv = static_cast<IUseAnyTool*>(this);
else if (riid == IID_IUnknown)
*ppv = static_cast<ILoveCOM*>(this);
else {
*ppv = 0;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CoTaoOfCPP::AddRef(void) {
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CoTaoOfCPP::Release(void) {
InterlockedDecrement(&m_cRef);
if(m_cRef == 0) {
delete this;
return 0;
} else
return m_cRef;
}
Figure 4 Declaring CTaoOfMFC
#include "taoofcom.h"
#include "taoofcom_i.c"
////////////////////////////////////////////////////////////////
// CTaoOfMFC command target
class CTaoOfMFC : public CCmdTarget
{
// declares the class object:
DECLARE_OLECREATE(CTaoOfMFC)
// add the queryinterface lookup table
DECLARE_INTERFACE_MAP()
// declare the nested classes
BEGIN_INTERFACE_PART(LoveCOMObj, ILoveCOM)
STDMETHODIMP DevelopInterface(void);
STDMETHODIMP ThenDevelopImplementation(void);
END_INTERFACE_PART(LoveCOMObj)
BEGIN_INTERFACE_PART(UseAnyToolObj, IUseAnyTool)
STDMETHODIMP UseCPP(void);
STDMETHODIMP UseMFC(void);
STDMETHODIMP UseATL(void);
STDMETHODIMP UseVB(void);
STDMETHODIMP UseJava(void);
END_INTERFACE_PART(UseAnyToolObj)
// ClassWizard stuff goes next…
};
Figure 5 Implementing CTaoOfMFC
IMPLEMENT_OLECREATE(CTaoOfMFC, "CTaoOfMFC",
0xCAB4A966, 0xA1C4, 0x11d1,
0x8C, 0xAA, 0xBF, 0x73, 0x5D, 0xC4, 0x0B, 0x69);
BEGIN_INTERFACE_MAP(CTaoOfMFC, CCmdTarget)
INTERFACE_PART(CTaoOfMFC, IID_ILoveCOM, LoveCOMObj)
INTERFACE_PART(CTaoOfMFC, IID_IUseAnyTool, UseAnyToolObj)
END_INTERFACE_MAP()
STDMETHODIMP_(ULONG)
CTaoOfMFC::XLoveCOMObj::AddRef(void)
{
METHOD_PROLOGUE(CTaoOfMFC, LoveCOMObj)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG)
CTaoOfMFC::XLoveCOMObj::Release(void)
{
METHOD_PROLOGUE(CTaoOfMFC, LoveCOMObj)
return pThis->ExternalRelease();
}
STDMETHODIMP
CTaoOfMFC::XLoveCOMObj::QueryInterface(REFIID riid,
void **ppv) {
METHOD_PROLOGUE(CTaoOfMFC, LoveCOMObj)
return pThis->ExternalQueryInterface(&riid, ppv);
}
STDMETHODIMP_(ULONG)
CTaoOfMFC::XUseAnyToolObj::AddRef(void)
{
METHOD_PROLOGUE(CTaoOfMFC, UseAnyToolObj)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG)
CTaoOfMFC::XUseAnyToolObj::Release(void)
{
METHOD_PROLOGUE(CTaoOfMFC, UseAnyToolObj)
return pThis->ExternalRelease();
}
STDMETHODIMP
CTaoOfMFC::XUseAnyToolObj::QueryInterface(REFIID riid,
void **ppv) {
METHOD_PROLOGUE(CTaoOfMFC, UseAnyToolObj)
return pThis->ExternalQueryInterface(&riid, ppv);
}
Figure 6 ATL-implemented Interfaces
#include "taoofcom.h"
#include "taoofcom_i.c"
///////////////////////////////////////////////////////////////
// CTaoOfATL
class ATL_NO_VTABLE CTaoOfATL :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTaoOfATL, &CLSID_TaoOfATL>,
public ILoveCOM,
public IUseAnyTool,
public IDispatchImpl<ITaoOfATL, &IID_ITaoOfATL, &LIBID_TAOOFATLLib>
{
public:
CTaoOfATL()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TAOOFATL)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CTaoOfATL)
COM_INTERFACE_ENTRY(ITaoOfATL)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ILoveCOM)
COM_INTERFACE_ENTRY(IUseAnyTool)
END_COM_MAP()
// ITaoOfATL
public:
STDMETHODIMP DevelopInterface(void);
STDMETHODIMP ThenDevelopImplementation(void);
// IUseAnyTool
STDMETHODIMP UseCPP(void);
STDMETHODIMP UseMFC(void);
STDMETHODIMP UseATL(void);
STDMETHODIMP UseVB(void);
STDMETHODIMP UseJava(void);
};
Figure 8 Interfaces in Visual Basic
Private Sub ILoveCOM_DevelopInterface()
MsgBox "I love to develop the interface first."
End Sub
Private Sub ILoveCOM_ThenDevelopImplementation()
MsgBox "then develop the implementation."
End Sub
Private Sub IUseAnyTool_UseCPP()
MsgBox "Nothing escapes the eye of the C++ developer"
End Sub
Private Sub IUseAnyTool_UseMFC()
MsgBox "I hate macros"
End Sub
Private Sub IUseAnyTool_UseATL()
MsgBox "ATL takes care of grunge"
End Sub
Private Sub IUseAnyTool_UseVB()
MsgBox "Push the button and go"
End Sub
Private Sub IUseAnyTool_UseJava()
MsgBox "Yet another way to make COM classes"
End Sub