Programming with Microsoft Visual C++.NET 6ed [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming with Microsoft Visual C++.NET 6ed [Electronic resources] - نسخه متنی

George Shepherd, David Kruglinski

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید








The Ex22a Example: Simulated COM


The following files show code for a working "simulated COM" program, Ex22a. This is a Win32 console application (without the MFC library) that uses a class factory to construct an object of class CSpaceship, calls its interface functions, and then releases the spaceship. The

Interface.h header file contains the CSimulatedCmdTarget base class and the interface declarations that are used by both the client and component programs. The

Spaceship.h header file contains the spaceship-specific class declarations that are used in the component program.

Spaceship.cpp is the component that implements GetClassObject, and

Client.cpp is the client that calls GetClassObject. What's phony here is that both client and component code are linked within the same Ex22a.exe program. Thus, our simulated COM is not required to make the connection at run time. (You'll see how that's done later in this chapter .)

Interface.h






// definitions that make our code look like MFC code
#define BOOL int
#define DWORD unsigned int
#define TRUE 1
#define FALSE 0
#define TRACE printf
#define ASSERT assert
//----------definitions and macros-----------------------------
#define CLSID_CSpaceship 10
#define IID_IUnknown 0
#define IID_IClassFactory 1
#define IID_IMotion 2
#define IID_IVisual 3 // this macro for 16-bit Windows only
#define METHOD_PROLOGUE(theClass, localClass) theClass* pThis = ((theClass*)((char*)(this) - offsetof(theClass, m_x##localClass))); BOOL GetClassObject(int nClsid, int nIid, void** ppvObj);
//----------interface declarations--------------------------------
struct IUnknown
{
IUnknown() { TRACE("Entering IUnknown ctor %p\n", this); }
virtual BOOL QueryInterface(int nIid, void** ppvObj) = 0;
virtual DWORD Release() = 0;
virtual DWORD AddRef() = 0;
};
struct IClassFactory : public IUnknown
{
IClassFactory()
{ TRACE("Entering IClassFactory ctor %p\n", this); }
virtual BOOL CreateInstance(int nIid, void** ppvObj) = 0;
};
struct IMotion : public IUnknown
{
IMotion() { TRACE("Entering IMotion ctor %p\n", this); }
virtual void Fly() = 0; // pure
virtual int& GetPosition() = 0;
};
struct IVisual : public IUnknown
{
IVisual() { TRACE("Entering IVisual ctor %p\n", this); }
virtual void Display() = 0;
};
class CSimulatedCmdTarget // 'simulated' CSimulatedCmdTarget
{
public:
DWORD m_dwRef;
protected:
CSimulatedCmdTarget() {
TRACE("Entering CSimulatedCmdTarget ctor %p\n", this);
m_dwRef = 1; // implied first AddRef
}
virtual ~CSimulatedCmdTarget()
{ TRACE("Entering CSimulatedCmdTarget dtor %p\n", this); }
DWORD ExternalRelease() {
TRACE("Entering CSimulatedCmdTarget::ExternalRelease--RefCount = %ld\n",
m_dwRef);
if (m_dwRef == 0)
return 0;
if(--m_dwRef == 0L) {
TRACE("deleting\n");
delete this;
return 0;
}
return m_dwRef;
}
DWORD ExternalAddRef() { return ++m_dwRef; }
};












Spaceship.h






class CSpaceship;
//----------class declarations-------------------------------------
class CSpaceshipFactory : public CSimulatedCmdTarget
{
public:
CSpaceshipFactory()
{ TRACE("Entering CSpaceshipFactory ctor %p\n", this); }
~CSpaceshipFactory()
{ TRACE("Entering CSpaceshipFactory dtor %p\n", this); }
BOOL ExternalQueryInterface(int lRid, void** ppvObj);
class XClassFactory : public IClassFactory
{
public:
XClassFactory()
{ TRACE("Entering XClassFactory ctor %p\n", this); }
virtual BOOL QueryInterface(int lRid, void** ppvObj);
virtual DWORD Release();
virtual DWORD AddRef();
virtual BOOL CreateInstance(int lRid, void** ppvObj);
} m_xClassFactory;
friend class XClassFactory;
};
class CSpaceship : public CSimulatedCmdTarget
{
private:
int m_nPosition; // We can access these from
// all the interfaces
int m_nAcceleration;
int m_nColor;
public:
CSpaceship() {
TRACE("Entering CSpaceship ctor %p\n", this);
m_nPosition = 100;
m_nAcceleration = 101;
m_nColor = 102;
}
~CSpaceship()
{ TRACE("Entering CSpaceship dtor %p\n", this); }
BOOL ExternalQueryInterface(int lRid, void** ppvObj);
class XMotion : public IMotion
{
public:
XMotion()
{ TRACE("Entering XMotion ctor %p\n", this); }
virtual BOOL QueryInterface(int lRid, void** ppvObj);
virtual DWORD Release();
virtual DWORD AddRef();
virtual void Fly();
virtual int& GetPosition();
} m_xMotion;
class XVisual : public IVisual
{
public:
XVisual() { TRACE("Entering XVisual ctor\n"); }
virtual BOOL QueryInterface(int lRid, void** ppvObj);
virtual DWORD Release();
virtual DWORD AddRef();
virtual void Display();
} m_xVisual;
friend class XVisual; // These must be at the bottom!
friend class XMotion;
friend class CSpaceshipFactory::XClassFactory;
};












Spaceship.cpp






#include <stdio.h>
#include <stddef.h> // for offsetof in METHOD_PROLOGUE
#include <ASSERT.h>
#include "Interface.h"
#include "Spaceship.h"
CSpaceshipFactory g_factory;
//----------member functions----------------------------------------
BOOL CSpaceshipFactory::ExternalQueryInterface(int nIid,
void** ppvObj) {
TRACE(
"Entering CSpaceshipFactory::ExternalQueryInterface--nIid = %d\n",
nIid);
switch (nIid) {
case IID_IUnknown:
case IID_IClassFactory:
*ppvObj = &m_xClassFactory;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceshipFactory::XClassFactory::QueryInterface(int nIid,
void** ppvObj) {
TRACE("Entering CSpaceshipFactory::XClassFactory::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalQueryInterface(nIid,
ppvObj); // delegate to
// CSpaceshipFactory
}
BOOL CSpaceshipFactory::XClassFactory::CreateInstance(int nIid,
void** ppvObj) {
TRACE("Entering CSpaceshipFactory::XClassFactory::CreateInstance\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
CSpaceship* pObj = new CSpaceship();
if (pObj->ExternalQueryInterface(nIid, ppvObj)) {
pObj->ExternalRelease(); // balance reference count
return TRUE;
}
return FALSE;
}
DWORD CSpaceshipFactory::XClassFactory::Release() {
TRACE("Entering CSpaceshipFactory::XClassFactory::Release\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceshipFactory::XClassFactory::AddRef() {
TRACE("Entering CSpaceshipFactory::XClassFactory::AddRef\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
BOOL CSpaceship::ExternalQueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::ExternalQueryInterface--nIid = %d\n",
nIid);
switch (nIid) {
case IID_IUnknown:
case IID_IMotion:
*ppvObj = &m_xMotion; // Both IMotion and IVisual are derived
break; // from IUnknown, so either pointer will do
case IID_IVisual:
*ppvObj = &m_xVisual;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceship::XMotion::QueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::XMotion::QueryInterface--nIid = %d\n",
nIid);
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to
// CSpaceship
}
DWORD CSpaceship::XMotion::Release() {
TRACE("Entering CSpaceship::XMotion::Release\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XMotion::AddRef() {
TRACE("Entering CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XMotion::Fly() {
TRACE("Entering CSpaceship::XMotion::Fly\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("this = %p, pThis = %p\n", this, pThis);
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
}
int& CSpaceship::XMotion::GetPosition() {
TRACE("Entering CSpaceship::XMotion::GetPosition\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("this = %p, pThis = %p\n", this, pThis);
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);
return pThis->m_nPosition;
}
BOOL CSpaceship::XVisual::QueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::XVisual::QueryInterface--nIid = %d\n",
nIid);
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to
// CSpaceship
}
DWORD CSpaceship::XVisual::Release() {
TRACE("Entering CSpaceship::XVisual::Release\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XVisual::AddRef() {
TRACE("Entering CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XVisual::Display() {
TRACE("Entering CSpaceship::XVisual::Display\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
TRACE("this = %p, pThis = %p\n", this, pThis);
TRACE("m_nPosition = %d\n", pThis->m_nPosition);
TRACE("m_nColor = %d\n", pThis->m_nColor);
}
//----------simulates COM component ----------------------------------
// In real COM, this would be DllGetClassObject, which would be called
// whenever a client called CoGetClassObject
BOOL GetClassObject(int nClsid, int nIid, void** ppvObj)
{
ASSERT(nClsid == CLSID_CSpaceship);
ASSERT((nIid == IID_IUnknown) || (nIid == IID_IClassFactory));
return g_factory.ExternalQueryInterface(nIid, ppvObj);
// Refcount is 2, which prevents accidental deletion
}












Client.cpp






#include <stdio.h>
#include <stddef.h> // for offsetof in METHOD_PROLOGUE
#include <assert.h>
#include "interface.h"
//----------main program---------------------------------------------
int main() // simulates OLE client program
{
TRACE("Entering client main\n");
IUnknown* pUnk; // If you declare these void*, you lose type-safety
IMotion* pMot;
IVisual* pVis;
IClassFactory* pClf;
GetClassObject(CLSID_CSpaceship, IID_IClassFactory,
(void**) &pClf);
pClf->CreateInstance(IID_IUnknown, (void**) &pUnk);
pUnk->QueryInterface(IID_IMotion, (void**) &pMot); // All three
pMot->QueryInterface(IID_IVisual, (void**) &pVis); // pointers
// should work
TRACE("main: pUnk = %p, pMot = %p, pDis = %p\n", pUnk,
pMot, pVis);
// Test all the interface virtual functions
pMot->Fly();
int nPos = pMot->GetPosition();
TRACE("nPos = %d\n", nPos);
pVis->Display();
pClf->Release();
pUnk->Release();
pMot->Release();
pVis->Release();
return 0;
}












/ 319