我遇到一个问题,即 IConnectionPoint :: Advise 调用返回 E_NOTIMPL 。这可能是因为连接点仅允许一个连接 - MSDN。
注意:
S8.tlh :C ++源代码相当于Win32类型库S8.tlb:
struct __declspec(uuid("090910c3-28c3-45fe-861d-edcf11aa9788"))
IS8SimulationEvents : IDispatch
{
// Methods:
HRESULT S8SimulationReset ( );
HRESULT S8SimulationEndRun ( );
HRESULT S8SimulationCustomEvent (
BSTR * TextInfo );
HRESULT S8SimulationOpened ( );
HRESULT S8SimulationEndTrial ( );
HRESULT S8SimulationOEMEvent (
BSTR * TextInfo );
HRESULT S8SimulationReadyToClose ( );
HRESULT S8SimulationUserMessage (
long * Answer,
BSTR * TextMsg,
long ValidAnswers );
};
实施类接收器 - 处理事件通知:
class Sink : public IS8SimulationEvents
{
public:
Sink(){
m_dwRefCount = 0;
};
~Sink(){};
/*
* IS8SimulationEvent interface functions
*/
HRESULT S8SimulationEndTrial()
{
cout << "Simulation complete." << endl;
return S_OK;;
};
HRESULT S8SimulationOpened()
{
cout << "Simulation open." << endl;
return S_OK;
};
HRESULT S8SimulationReadyToClose()
{
cout << "Simulation ready to close" << endl;
return S_OK;
};
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
};
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if (0 == m_dwRefCount)
{
delete this;
}
return m_dwRefCount;
};
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID iid ,
void **ppvObject)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
};
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE GetIDsOfNames(
REFIID riid,
LPOLESTR *rgszNames,
UINT cNames,
LCID lcid,
DISPID *rgDispId)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE GetTypeInfo(
unsigned int iTInfo,
LCID lcid,
ITypeInfo FAR* FAR* ppTInfo)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr)
{
HRESULT hresult = S_OK;
if (pDispParams)
{
switch (dispIdMember) {
case 1:
return S8SimulationEndTrial();
case 2:
return S8SimulationOpened();
case 3:
return S8SimulationReadyToClose();
default:
return E_NOTIMPL;
}
}
return E_NOTIMPL;
}
private:
DWORD m_dwRefCount;
public:
void SetupConnectionPoint (IS8Simulation *pis8)
{
HRESULT hresult;
IConnectionPointContainer *pContainer = NULL;
IConnectionPoint *pConnection = NULL;
IUnknown *pSinkUnk = NULL;
Sink *pSink = NULL;
DWORD dwAdvise;
dwAdvise = 0;
hresult = pis8->QueryInterface(
__uuidof(IConnectionPointContainer),
(void **) &pContainer);
if (SUCCEEDED(hresult))
{
cout << "IConnectionPointContainer inteface supported." << endl;
} else {
cerr << "Error: No such interface supported." << endl;
exit (hresult);
}
__uuidof(IS8SimulationEvents),
&pConnection);
switch (HRESULT_CODE(hresult)) {
case NOERROR:
cout << "Obtained valid interface pointer." << endl;
break;
case E_POINTER:
cerr << "Invalid pointer: the address is not valid." << endl;
exit (hresult);
break;
case CONNECT_E_NOCONNECTION:
cerr << "This connectable object not support the "
"outgoing interface specified." << endl;
exit (hresult);
break;
case E_UNEXPECTED:
default:
cerr << "Catastrophic failure." << endl;
exit (hresult);
break;
}
pContainer->Release();
hresult = pSink->QueryInterface(
__uuidof(IUnknown),
(void **)&pSinkUnk);
if (FAILED(hresult))
{
exit (EXIT_FAILURE);
}
hresult = pConnection->Advise(
pSinkUnk,
&dwAdvise);
switch (HRESULT_CODE(hresult)) {
case NOERROR:
cout << "The connection has been established and "
"*dwAdvise has the connection token." << endl;
break;
case E_POINTER:
cerr << "Invalid pointer: "
"the value pSinkUnk or dwAdvise is not valid." << endl;
exit (hresult);
break;
case CONNECT_E_ADVISELIMIT:
cerr << "The connection point has already reached "
"its limit of connections and cannot accept "
"any more." << endl;
exit (hresult);
break;
case CONNECT_E_CANNOTCONNECT:
cerr << "The sink does not support the interface "
"required by this connection point." << endl;
exit (hresult);
break;
case E_NOTIMPL:
break;
case E_UNEXPECTED:
default:
cerr << "Catastrophic failure." << endl;
exit (hresult);
break;
}
return;
}
};
在接收器类中实施 IUnknown 接口
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
};
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if (0 == m_dwRefCount)
{
delete this;
}
return m_dwRefCount;
};
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
};
问题:
答案 0 :(得分:1)
请再次阅读MSDN文章。
A connection point that allows only one interface can return E_NOTIMPL FROM the IConnectionPoint::EnumConnections method EnumConnections : E_NOTIMPL The connection point does not support enumeration.
IConnectionPoint :: Advise需要回复
CONNECT_E_ADVISELIMIT
当他的连接点已达到其连接限制并且不能再接受时。
-
迈克尔
答案 1 :(得分:0)
AtlAdvise应该使连接点在事件接收器上调用QI。 您无法确定它可能会调用QI的次数或次数。
建议:在eventsink中引用类似的内容来确定查询的事件接口是否正确。
void GuidToString(PTCHAR s, LPGUID piid )
{
_stprintf(s, _T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
piid->Data1, piid->Data2,
piid->Data3,
piid->Data4[0], piid->Data4[1],
piid->Data4[2], piid->Data4[3],
piid->Data4[4], piid->Data4[5],
piid->Data4[6], piid->Data4[7]);
// Outputdebugstr (s)
}
事件接收器QueryInterface
应该执行类似
if (iid == IID_IUnknown || iid == IID_AppEvents)
*ppObj = (AppEvents*)this;
因此它只返回正确的界面。
答案 2 :(得分:0)
在调用Advise调用时,COM库为IUnknown,IMarshall等许多接口调用QI。
正如迈克尔指出的MSDN文章,它说它只为EnumConnections API而不是Advise返回E_NOTIMPL。我怀疑QI返回E_NOTIMPL。因此,请尝试跟踪Advise API。你会了解QI的失败。
答案 3 :(得分:0)
使用以下实施 QI :
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if (iid == __uuidof(IUnknown) || iid == __uuidof(IS8SimulationEvents))
{
*ppvObject = (IS8SimulationEvents*)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
m_dwRefCount++;
return S_OK;
};