1.建立常规DLL(在”附加功能”里面选择”自动化”选项)
2.创建接口并提供相应的IID
struct IMotion:public IUnknown{
STDMETHOD_(void,Fly)()PURE;
STDMETHOD_(int&,GetPosition)()PURE;
};
struct IVisual:public IUnknown {
STDMETHOD_(void,Display)()PURE;
};
// {B6169E 5C -6AC 9-403e-ADE4-5CF 575A 645EB}
static const IID IID_IMotion =
{ 0xb6169e 5c , 0x 6ac 9, 0x403e, { 0xad, 0xe4, 0x 5c , 0xf5, 0x75, 0xa6, 0x45, 0xeb } };
// {EDD32B47-5930-4d45-9181-5ABECD138CAC}
static const IID IID_IVisual =
{ 0xedd32b47, 0x5930, 0x4d45, { 0x91, 0x81, 0x 5a , 0xbe, 0xcd, 0x13, 0x 8c , 0xac } };
3.创建COM类(在”自动化”选项里面选择”可按类型ID创建”)
4.添加接口定义:,从CCmdTarget派生
在COM类定义中添加接口
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)
在COM类实现文件里面添加接口映射表
BEGIN_INTERFACE_MAP(CSpaceship, CCmdTarget)
INTERFACE_PART(CSpaceship, IID_ISpaceship, Dispatch)
INTERFACE_PART(CSpaceship,IID_IMotion,Motion)
INTERFACE_PART(CSpaceship,IID_IVisual,Visual)
END_INTERFACE_MAP()
5.处理接口函数:(以下三个函数是所有接口都要实现的)
(获取pThis METHOD_PROLOGUE(CSpaceship, Motion))
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);
}
以下为客户端实现
1..添加COM支持
添加头文件 #include<afxole.h>
初始化COM通信: ::CoInitialize(NULL);
所有代码:
服务器端:
//Interface.h
struct IMotion:public IUnknown{
STDMETHOD_(void,Fly)()PURE;
STDMETHOD_(int&,GetPosition)()PURE;
};
struct IVisual:public IUnknown {
STDMETHOD_(void,Display)()PURE;
};
// {B6169E 5C -6AC 9-403e-ADE4-5CF 575A 645EB}
static const IID IID_IMotion =
{ 0xb6169e 5c , 0x 6ac 9, 0x403e, { 0xad, 0xe4, 0x 5c , 0xf5, 0x75, 0xa6, 0x45, 0xeb } };
// {EDD32B47-5930-4d45-9181-5ABECD138CAC}
static const IID IID_IVisual =
{ 0xedd32b47, 0x5930, 0x4d45, { 0x91, 0x81, 0x 5a , 0xbe, 0xcd, 0x13, 0x 8c , 0xac } };
//Spaceship.h头文件
#pragma once
#include "Interface.h"
// CSpaceship 命令目标
void ITrace(REFIID iid, const char* str);
class CSpaceship : public CCmdTarget
{
DECLARE_DYNCREATE(CSpaceship)
private:
int m_nPosition;
int m_nAcceleration;
int m_nColor;
public:
CSpaceship();
virtual ~CSpaceship();
virtual void OnFinalRelease();
protected:
DECLARE_MESSAGE_MAP()
DECLARE_OLECREATE(CSpaceship)
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()
//以下为手动添加
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)
};
// Spaceship.cpp : 实现文件
//
#include "stdafx.h"
#include "Ex22b.h"
#include "Spaceship.h"
// CSpaceship
IMPLEMENT_DYNCREATE(CSpaceship, CCmdTarget)
CSpaceship::CSpaceship()
{
EnableAutomation();
// 为了使应用程序在 OLE 自动化对象处于活动状态时保持
// 运行,构造函数调用 AfxOleLockApp。
TRACE("CSpaceship/n");
m_nAcceleration=101;
m_nPosition=100;
m_nColor=102;
AfxOleLockApp();
}
CSpaceship::~CSpaceship()
{
// 为了在用 OLE 自动化创建所有对象后终止应用程序,
// 析构函数调用 AfxOleUnlockApp。
TRACE("~Spaceship/n");
AfxOleUnlockApp();
}
void CSpaceship::OnFinalRelease()
{
// 释放了对自动化对象的最后一个引用后,将调用
// OnFinalRelease。基类将自动
// 删除该对象。在调用该基类之前,请添加您的
// 对象所需的附加清除代码。
CCmdTarget::OnFinalRelease();
}
BEGIN_MESSAGE_MAP(CSpaceship, CCmdTarget)
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CSpaceship, CCmdTarget)
END_DISPATCH_MAP()
// 注意: 我们添加 IID_ISpaceship 支持
//以支持来自 VBA 的类型安全绑定。此 IID 必须同附加到 .IDL 文件中的
//调度接口的 GUID 匹配。
// {1DE882B0-C6AE-4DFF -9F 3F -E02E4D9D613E}
static const IID IID_ISpaceship =
{ 0x1DE882B0, 0xC6AE, 0x4DFF, { 0x 9F , 0x 3F , 0xE0, 0x2E, 0x4D, 0x9D, 0x61, 0x3E } };
BEGIN_INTERFACE_MAP(CSpaceship, CCmdTarget)
INTERFACE_PART(CSpaceship, IID_ISpaceship, Dispatch)
INTERFACE_PART(CSpaceship,IID_IMotion,Motion) //手动添加
INTERFACE_PART(CSpaceship,IID_IVisual,Visual) //手动添加
END_INTERFACE_MAP()
// {E9BA3078-5EC5 -4A 65-B805 -9C 341D6DF 00A }
IMPLEMENT_OLECREATE_FLAGS(CSpaceship, "Ex22b.Spaceship", afxRegApartmentThreading, 0xe9ba3078, 0x5ec5, 0x 4a 65, 0xb8, 0x5, 0x 9c , 0x34, 0x1d, 0x6d, 0xf0, 0xa)
// CSpaceship 消息处理程序
//以下为手动添加
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);
}
客户端测试代码:
// Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <afxole.h>
#include "../Ex22b/Interface.h"
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
CLSID clsid;
LPCLASSFACTORY pClf;
LPUNKNOWN pUnk;
IMotion* pMot;
IVisual* pVis;
HRESULT hr;
if ((hr = ::CLSIDFromProgID(L"Ex22b.Spaceship", &clsid)) != NOERROR) {
TRACE("unable to find Program ID -- error = %x/n", hr);
return -1;
}
if ((hr = ::CoGetClassObject(clsid, CLSCTX_INPROC_SERVER,
NULL, IID_IClassFactory, (void **) &pClf)) != NOERROR) {
TRACE("unable to find CLSID -- error = %x/n", hr);
return -1;
}
pClf->CreateInstance(NULL, 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();
AfxMessageBox("Test succeeded. See Debug window for output.");
return 0;
}