1.建立常規DLL(在”附加功能”裏面選擇”自動化”選項)
2.創建接口並提供相應的IID
struct IMotion:public IUnknown{
STDMETHOD_(void,Fly)()PURE;
STDMETHOD_(int&,GetPosition)()PURE;
};
struct IVisual:public IUnknown {
STDMETHOD_(void,Display)()PURE;
};
// {B6169E5C-6AC9-403e-ADE4-5CF575A645EB}
static const IID IID_IMotion =
{ 0xb6169e5c, 0x6ac9, 0x403e, { 0xad, 0xe4, 0x5c, 0xf5, 0x75, 0xa6, 0x45, 0xeb } };
// {EDD32B47-5930-4d45-9181-5ABECD138CAC}
static const IID IID_IVisual =
{ 0xedd32b47, 0x5930, 0x4d45, { 0x91, 0x81, 0x5a, 0xbe, 0xcd, 0x13, 0x8c, 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;
};
// {B6169E5C-6AC9-403e-ADE4-5CF575A645EB}
static const IID IID_IMotion =
{ 0xb6169e5c, 0x6ac9, 0x403e, { 0xad, 0xe4, 0x5c, 0xf5, 0x75, 0xa6, 0x45, 0xeb } };
// {EDD32B47-5930-4d45-9181-5ABECD138CAC}
static const IID IID_IVisual =
{ 0xedd32b47, 0x5930, 0x4d45, { 0x91, 0x81, 0x5a, 0xbe, 0xcd, 0x13, 0x8c, 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-9F3F-E02E4D9D613E}
static const IID IID_ISpaceship =
{ 0x1DE882B0, 0xC6AE, 0x4DFF, { 0x9F, 0x3F, 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-4A65-B805-9C341D6DF00A}
IMPLEMENT_OLECREATE_FLAGS(CSpaceship, "Ex22b.Spaceship", afxRegApartmentThreading, 0xe9ba3078, 0x5ec5, 0x4a65, 0xb8, 0x5, 0x9c, 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;
}