我用一个简单的COM对象编写了一个简单的COM DLL inproc服务器。 COM对象实现了一个连接点。
我知道如何创建一个派生自IDispEventImpl
的ATL客户端,并使用汇点图简化此过程。
但是,出于演示的目的,我想创建一个win32控制台应用程序,它使用一个调用我的简单COM对象的类,然后充当连接点接收器。
我不知道如何提供IDispatch
的实现 - 有人可以推荐这方面的文档,因为我找不到任何内容(我有ATL Internals,但似乎没有涵盖我需要的东西。)
这是我已经上过的课程:
#pragma once
#include <iostream>
using namespace std;
// Because we're implementing a connection points sink (_IPogFarmEvents)
// in a non-ATL class, we must provide implementations for IUnknown and IDispatch.
class KidWithAPogFarm : public _IPogFarmEvents
{
private:
DWORD m_dwRefCount;
LONG m_lNumPogs;
public:
KidWithAPogFarm() :
m_dwRefCount (0),
m_lNumPogs (0)
{
}
~KidWithAPogFarm()
{
}
// -- IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if (iid == DIID__IPogFarmEvents)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
if (iid == IID_IUnknown)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if ( 0 == m_dwRefCount)
delete this;
return l;
}
// -- IDispatch
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo )
{
return E_NOTIMPL;
}
STDMETHODIMP GetIDsOfNames(const IID &riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId )
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr )
{
return E_NOT_IMPL;
}
// -- IAntFarmEvents
STDMETHODIMP OnFarmCreated(LONG lInitialPopulation)
{
m_lNumPogs = lInitialPopulation;
cout << "The kid has a pog farm with " << m_lNumPogs << " pogs " << endl;
return S_OK;
}
};
答案 0 :(得分:2)
由于您已经拥有ATL
,因此您可以查看其来源并了解IDispatchImpl
如何完成所有这些工作。通过从同一模块中的类型库中读取数据来实现IDispatch
方法,因为当类型库已经存在时,它是最简单,最可靠的方法。
值得注意的是,对它进行演示是一个相当困难的话题 - 你需要编写很多代码,而这些代码并没有真正带来任何洞察力。如果您实现的事件接口不是从IDispatch
继承而是直接从IUnknown
继承,那么IMO你会好得多 - 这将演示事件如何工作而不会过多地关注{ {1}}内部运作。
答案 1 :(得分:1)
我认为最简单的方法是通过CreateStdDispatch
答案 2 :(得分:1)
您可以使用this IDispatch实施。
答案 3 :(得分:0)
这并不是您正在寻找的,但是FireBreath使用IDispatchEx和连接点来提供在IE中运行的ActiveX控件。因为FireBreath是允许插件一次编写并在所有主流浏览器中使用的抽象,所以需要手工编写IDispatch接口 - 包括连接点。
代码可能有点令人困惑,因为有一个模板化的mixin类用于向两个不同的COM对象类提供IDispatch和ConnectionPoints,但它可能会有所帮助。
你已经接受了答案,但也许它仍然会有所帮助。对不起,我没有早点看到这个问题。