The Ex22b Example: An MFC COM In-Process Component
The Ex22b example is an MFC regular DLL that incorporates a true COM version of the CSpaceship class you saw in Ex22a. The MFC DLL Wizard generated the




Interface.h
struct IMotion : public IUnknown
{
STDMETHOD_(void, Fly) () = 0;
STDMETHOD_(int&, GetPosition) () = 0;
};
struct IVisual : public IUnknown
{
STDMETHOD_(void, Display) () = 0;
};
Spaceship.h
#pragma once
void ITrace(REFIID iid, const char* str);
// CSpaceship command target
class CSpaceship : public CCmdTarget
{
DECLARE_DYNCREATE(CSpaceship)
private:
int m_nPosition; // We can access this from all the interfaces
int m_nAcceleration;
int m_nColor;
public:
CSpaceship();
virtual ~CSpaceship();
virtual void OnFinalRelease();
protected:
DECLARE_MESSAGE_MAP()
DECLARE_OLECREATE(CSpaceship)
BEGIN_INTERFACE_PART(Motion, IMotion)
STDMETHOD_(void, Fly) ();
STDMETHOD_(int&, GetPosition) ();
END_INTERFACE_PART(Motion)
BEGIN_INTERFACE_PART(Visual, IVisual)
STDMETHOD_(void, Display) ();
END_INTERFACE_PART(Visual)
DECLARE_INTERFACE_MAP()
};
Spaceship.cpp
// Spaceship.cpp : implementation file
//
#include "stdafx.h"
#include "Ex22b.h"
#include "Interface.h"
#include "Spaceship.h"
// CSpaceship
// {692D03A4-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IMotion =
{ 0x692d03a4, 0xc689, 0x11ce,
{ 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };
// {692D03A5-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IVisual =
{ 0x692d03a5, 0xc689, 0x11ce,
{ 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };
IMPLEMENT_DYNCREATE(CSpaceship, CCmdTarget)
CSpaceship::CSpaceship()
{
TRACE("CSpaceship ctor\n");
m_nPosition = 100;
m_nAcceleration = 101;
m_nColor = 102;
// To keep the application running as long as an OLE automation
// object is active, the constructor calls AfxOleLockApp.
AfxOleLockApp();
}
CSpaceship::~CSpaceship()
{
TRACE("CSpaceship dtor\n");
// To terminate the application when all objects created with
// OLE automation, the destructor calls AfxOleUnlockApp.
AfxOleUnlockApp();
}
void CSpaceship::OnFinalRelease()
{
// When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// delete the object. Add additional cleanup required for your
// object before calling the base class.
delete this;
}
BEGIN_MESSAGE_MAP(CSpaceship, CCmdTarget)
END_MESSAGE_MAP()
// Note: we add support for IID_ISpaceship to support typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .IDL file.
// {E39B5EB0-A0DA-43F3-B9B0-206CF10890C1}
static const IID IID_ISpaceship =
{ 0xE39B5EB0, 0xA0DA, 0x43F3,
{ 0xB9, 0xB0, 0x20, 0x6C, 0xF1, 0x8, 0x90, 0xC1 } };
BEGIN_INTERFACE_MAP(CSpaceship, CCmdTarget)
INTERFACE_PART(CSpaceship, IID_IMotion, Motion)
INTERFACE_PART(CSpaceship, IID_IVisual, Visual)
END_INTERFACE_MAP()
// {13C4472C-84BB-4ED6-8164-83ED8EB136B5}
IMPLEMENT_OLECREATE_FLAGS(CSpaceship, "Ex22b.Spaceship",
afxRegApartmentThreading, 0x13c4472c, 0x84bb, 0x4ed6, 0x81,
0x64, 0x83, 0xed, 0x8e, 0xb1, 0x36, 0xb5)
STDMETHODIMP_(ULONG) CSpaceship::XMotion::AddRef()
{
TRACE("CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CSpaceship::XMotion::Release()
{
TRACE("CSpaceship::XMotion::Release\n");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalRelease();
}
STDMETHODIMP CSpaceship::XMotion::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
ITrace(iid, "CSpaceship::XMotion::QueryInterface");
METHOD_PROLOGUE(CSpaceship, Motion)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP_(void) CSpaceship::XMotion::Fly()
{
TRACE("CSpaceship::XMotion::Fly\n");
METHOD_PROLOGUE(CSpaceship, Motion)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
return;
}
STDMETHODIMP_(int&) CSpaceship::XMotion::GetPosition()
{
TRACE("CSpaceship::XMotion::GetPosition\n");
METHOD_PROLOGUE(CSpaceship, Motion)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
return pThis->m_nPosition;
}
STDMETHODIMP_(ULONG) CSpaceship::XVisual::AddRef()
{
TRACE("CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CSpaceship::XVisual::Release()
{
TRACE("CSpaceship::XVisual::Release\n");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalRelease();
}
STDMETHODIMP CSpaceship::XVisual::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
ITrace(iid, "CSpaceship::XVisual::QueryInterface");
METHOD_PROLOGUE(CSpaceship, Visual)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP_(void) CSpaceship::XVisual::Display()
{
TRACE("CSpaceship::XVisual::Display\n");
METHOD_PROLOGUE(CSpaceship, Visual)
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nColor = %d\n", pThis->m_nColor);
}
void ITrace(REFIID iid, const char* str)
{
OLECHAR* lpszIID;
::StringFromIID(iid, &lpszIID);
CString strTemp(lpszIID);
TRACE("%s - %s\n", (const char*) strTemp, (const char*) str);
AfxFreeTaskMem(lpszIID);
}