VC中响应COM组件的事件失败,高分求助高人啊!!

Python 2011-10-22 01:32:48
我有一个普通的COM组件,其中有两个事件,我想在MFC Dialog中使用该组件并响应其事件,我生成了一个事件响应类,并实现了接口,该类程序全部由VC 2010自动生成,代码如下:
// DSSimpleObjSink.h : Declaration of the CDSSimpleObjSink

#pragma once
#include "resource.h" // main symbols



#include "Test in VC_i.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;


// CDSSimpleObjSink

class ATL_NO_VTABLE CDSSimpleObjSink :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CDSSimpleObjSink, &CLSID_DSSimpleObjSink>,
public IDispatchImpl<IDSSimpleObjSink, &IID_IDSSimpleObjSink, &LIBID_TestinVCLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispatchImpl<_IDSSimpleObjEvents, &__uuidof(_IDSSimpleObjEvents), &LIBID_DataEngineTestLib, /* wMajor = */ 1>
{
public:
CDSSimpleObjSink()
{
}

DECLARE_REGISTRY_RESOURCEID(IDR_DSSIMPLEOBJSINK)

DECLARE_NOT_AGGREGATABLE(CDSSimpleObjSink)

BEGIN_COM_MAP(CDSSimpleObjSink)
COM_INTERFACE_ENTRY(IDSSimpleObjSink)
COM_INTERFACE_ENTRY2(IDispatch, _IDSSimpleObjEvents)
COM_INTERFACE_ENTRY(_IDSSimpleObjEvents)
END_COM_MAP()


DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()
{
return S_OK;
}

void FinalRelease()
{
}

public:


// _IDSSimpleObjEvents Methods
public:
STDMETHOD(UpdateUI)(long BusinessID)
{
int i = BusinessID;
return 1;
}
STDMETHOD(PrePrint)(BSTR * PrintContent)
{
int i = 0;
return 1;
}
};

OBJECT_ENTRY_AUTO(__uuidof(DSSimpleObjSink), CDSSimpleObjSink)


我在Dialog中使用方法如下:
	HRESULT hr = CoCreateInstance(CLSID_DSSimpleObj, NULL, CLSCTX_INPROC_SERVER,
IID_IDSSimpleObj, (LPVOID*)&m_pDSSimpleObj);

if (FAILED(hr))
{
m_pDSSimpleObj = 0;

MessageBox(_T("Create DSSimpleObj failed."));

return false;
}

//CComPtr<IConnectionPoint> pPC;
CComQIPtr<IConnectionPointContainer, &__uuidof(IConnectionPointContainer)> pCPC(m_pDSSimpleObj);
pCPC->FindConnectionPoint(DIID__IDSSimpleObjEvents, &m_pPC);

CComPtr<IUnknown> pUnk;
//CDSSimpleObjSink* pDSSimpleObjEvent = new CComObject<CDSSimpleObjSink>;
m_pDSSimpleObjEvent = new CComObject<CDSSimpleObjSink>;
m_pDSSimpleObjEvent->QueryInterface(IID_IUnknown, (void**)&pUnk);
m_pPC->Advise(pUnk, &m_dwCookie);


其中声明如下:
	CComPtr<IDSSimpleObj> m_pDSSimpleObj;
DWORD m_dwCookie;
CDSSimpleObjSink* m_pDSSimpleObjEvent;
CComPtr<IConnectionPoint> m_pPC;


调试时,发现函数UpdateUI或者PrePrint都没有进入,不知怎么回事,请高人帮帮忙啊,谢谢啦!!
...全文
335 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
Python 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fishion 的回复:]
看着你像是用错了,参考下面的
http://www.kuqin.com/components/20070908/959.html
[/Quote]

这个我看过的,我不想用自己实现Invoke这种方式,想通过框架方式实现。难道必须用Invoke这种方式吗?
Python 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 ysjyniiq 的回复:]
//给你换个血
class CDSSimpleObjSink :
public IDispEventImpl <1, CDSSimpleObjSink>//它会使用默认的TYPELIB
{
public:
CDSSimpleObjSink()
{
}

BEGIN_SINK_MAP(CDSSimpleObjSink)
SINK_ENTRY(1/*id*/……
[/Quote]

m_pDSSimpleObjEvent->Advise(m_pDSSimpleObj);
这句返回E_NOINTERFACE
fishion 2011-10-24
  • 打赏
  • 举报
回复
看着你像是用错了,参考下面的
http://www.kuqin.com/components/20070908/959.html
Python 2011-10-24
  • 打赏
  • 举报
回复
谢谢各位了,参考了
微软的帮助:
http://msdn.microsoft.com/zh-cn/library/cc468024(v=VS.71).aspx
解决了问题,呵呵
gold_water 2011-10-24
  • 打赏
  • 举报
回复
加油!!!
redui 2011-10-24
  • 打赏
  • 举报
回复
IDispEventImpl也要调用Invoke,只不过它帮你封装好了,肯定是你还遗漏了什么,这么大段代码,我是没法帮你仔细核对的。
Python 2011-10-24
  • 打赏
  • 举报
回复
debug到ATL中去太累了,唉
用类似CSink的方法,自己实现Invoke,没有问题,我测试过了。
我觉得通过类似框架的方法,实现接口 的方法,应该也可以实现,就是不知道该怎么做,:(
ysjyniiq 2011-10-24
  • 打赏
  • 举报
回复
你一开始的方法,从原理上说应是可以的,解决这种问题,只有狠下心去,debug到ATL里面的代码里
WaistCoat07 2011-10-23
  • 打赏
  • 举报
回复
事件响应函数是由组件来调用的。
你的的COM组件事件是咋映射的。
ysjyniiq 2011-10-23
  • 打赏
  • 举报
回复
//给你换个血
class CDSSimpleObjSink :
public IDispEventImpl <1, CDSSimpleObjSink>//它会使用默认的TYPELIB
{
public:
CDSSimpleObjSink()
{
}

BEGIN_SINK_MAP(CDSSimpleObjSink)
SINK_ENTRY(1/*id*/, 1/*dispID*/, UpdateUI)
SINK_ENTRY(1, 2, PrePrint)
END_SINK_MAP()

// _IDSSimpleObjEvents Methods
public:
STDMETHOD(UpdateUI)(long BusinessID)
{
int i = BusinessID;
return 1;
}
STDMETHOD(PrePrint)(BSTR * PrintContent)
{
int i = 0;
return 1;
}
};

将这段
//CComPtr<IConnectionPoint> pPC;
CComQIPtr<IConnectionPointContainer, &__uuidof(IConnectionPointContainer)> pCPC(m_pDSSimpleObj);
pCPC->FindConnectionPoint(DIID__IDSSimpleObjEvents, &m_pPC);

CComPtr<IUnknown> pUnk;
//CDSSimpleObjSink* pDSSimpleObjEvent = new CComObject<CDSSimpleObjSink>;
m_pDSSimpleObjEvent = new CComObject<CDSSimpleObjSink>;
m_pDSSimpleObjEvent->QueryInterface(IID_IUnknown, (void**)&pUnk);
m_pPC->Advise(pUnk, &m_dwCookie);


换成
m_pDSSimpleObjEvent = new CDSSimpleObjSink;
m_pDSSimpleObjEvent->Advise(m_pDSSimpleObj);
Python 2011-10-23
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 ysjyniiq 的回复:]

1.
public IDispatchImpl<IDSSimpleObjSink, &IID_IDSSimpleObjSink, &LIBID_TestinVCLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,

2.
COM_INTERFACE_ENTRY(IDSSimpleObjSink)

把CDSSimpleObjSink 这两处删掉……
[/Quote]

还是一样。:(
ysjyniiq 2011-10-23
  • 打赏
  • 举报
回复
1.
public IDispatchImpl<IDSSimpleObjSink, &IID_IDSSimpleObjSink, &LIBID_TestinVCLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,

2.
COM_INTERFACE_ENTRY(IDSSimpleObjSink)

把CDSSimpleObjSink 这两处删掉试试


没必要双dispatch,ATL里也不建议双dispatch,如需要多个SINK,建议使用IDispEventImpl
Python 2011-10-23
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 redui 的回复:]

客户端在哪里映射DISPID的?没有正确映射DISPID,就会出现方法未发现的状况
[/Quote]

就是不知道客户端该如何映射DISPID啊。我客户端采用的是框架自动 实现接口 的方法,自动生成的代码
Python 2011-10-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 waistcoat07 的回复:]

事件响应函数是由组件来调用的。
你的的COM组件事件是咋映射的。
[/Quote]

COM组件代码框架均由ATL自动生成,如下:

// DSSimpleObj.h : Declaration of the CDSSimpleObj

#pragma once
#include "resource.h" // main symbols



#include "DataEngineTest_i.h"
#include "_IDSSimpleObjEvents_CP.h"


#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;


// CDSSimpleObj

class ATL_NO_VTABLE CDSSimpleObj :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CDSSimpleObj, &CLSID_DSSimpleObj>,
public IConnectionPointContainerImpl<CDSSimpleObj>,
public CProxy_IDSSimpleObjEvents<CDSSimpleObj>,
public IDSSimpleObj
{
public:
CDSSimpleObj()
{
}

DECLARE_REGISTRY_RESOURCEID(IDR_DSSIMPLEOBJ)


BEGIN_COM_MAP(CDSSimpleObj)
COM_INTERFACE_ENTRY(IDSSimpleObj)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CDSSimpleObj)
CONNECTION_POINT_ENTRY(__uuidof(_IDSSimpleObjEvents))
END_CONNECTION_POINT_MAP()


DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()
{
return S_OK;
}

void FinalRelease()
{
}

protected:
CComBSTR m_bstrStationID;

public:
STDMETHOD(get_StationID)(BSTR* pVal);
STDMETHOD(put_StationID)(BSTR newVal);
STDMETHOD(Enqueue)(LONG BusinessID);
};

OBJECT_ENTRY_AUTO(__uuidof(DSSimpleObj), CDSSimpleObj)




#pragma once

template<class T>
class CProxy_IDSSimpleObjEvents :
public ATL::IConnectionPointImpl<T, &__uuidof(_IDSSimpleObjEvents)>
{
public:
HRESULT Fire_UpdateUI(LONG BusinessID)
{
HRESULT hr = S_OK;
T * pThis = static_cast<T *>(this);
int cConnections = m_vec.GetSize();

for (int iConnection = 0; iConnection < cConnections; iConnection++)
{
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
pThis->Unlock();

IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

if (pConnection)
{
CComVariant avarParams[1];
avarParams[0] = BusinessID;
avarParams[0].vt = VT_I4;
CComVariant varResult;

DISPPARAMS params = { avarParams, NULL, 1, 0 };
hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL);
}
}
return hr;
}
HRESULT Fire_PrePrint(BSTR * PrintContent)
{
HRESULT hr = S_OK;
T * pThis = static_cast<T *>(this);
int cConnections = m_vec.GetSize();

for (int iConnection = 0; iConnection < cConnections; iConnection++)
{
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
pThis->Unlock();

IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

if (pConnection)
{
CComVariant avarParams[1];
avarParams[0].byref = PrintContent;
avarParams[0].vt = VT_BSTR|VT_BYREF;
CComVariant varResult;

DISPPARAMS params = { avarParams, NULL, 1, 0 };
hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL);
}
}
return hr;
}
};



// DataEngineTest.idl : IDL source for DataEngineTest
//

// This file will be processed by the MIDL tool to
// produce the type library (DataEngineTest.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
object,
uuid(1BA56D84-2F74-4C03-AD2B-030187D1F8C5),
pointer_default(unique)
]
interface IDSSimpleObj : IUnknown{
[propget] HRESULT StationID([out, retval] BSTR* pVal);
[propput] HRESULT StationID([in] BSTR newVal);
[] HRESULT Enqueue([in] LONG BusinessID);
};
[
uuid(B001CAAF-2AF4-4991-BD97-6FBBD4915D12),
version(1.0),
]
library DataEngineTestLib
{
importlib("stdole2.tlb");
[
uuid(BB4072F1-E58A-41D1-9BBF-068B2C471A42)
]
dispinterface _IDSSimpleObjEvents
{
properties:
methods:
[id(1)] HRESULT UpdateUI([in] LONG BusinessID);
[id(2)] HRESULT PrePrint([in,out] BSTR* PrintContent);
};
[
uuid(82452453-8CAB-472F-ACA8-03EDE01DE131)
]
coclass DSSimpleObj
{
[default] interface IDSSimpleObj;
[default, source] dispinterface _IDSSimpleObjEvents;
};
};



组件在C#中可以正常调用并响应事件啊。
redui 2011-10-23
  • 打赏
  • 举报
回复
客户端在哪里映射DISPID的?没有正确映射DISPID,就会出现方法未发现的状况
Python 2011-10-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 redui 的回复:]

组件也是你自己的?单步跟踪就能找到问题。
如果组件不是你的,要么组件并未触发事件,要么你根本没挂接到连接点上,看看Advise的返回值。
[/Quote]

组件是我自己的。首先Advise返回S_OK,没有问题。
跟踪进了自己的组件中,发现在最好返回了Mothed not found.
不知道怎么处理了。
redui 2011-10-22
  • 打赏
  • 举报
回复
组件也是你自己的?单步跟踪就能找到问题。
如果组件不是你的,要么组件并未触发事件,要么你根本没挂接到连接点上,看看Advise的返回值。
Python 2011-10-22
  • 打赏
  • 举报
回复
up
请帮忙啊
Python 2011-10-22
  • 打赏
  • 举报
回复
调试时,COM已触发事件,但事件响应函数没有进入,请教啊!

3,248

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧