失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > mfc工程中添加com接口支持

mfc工程中添加com接口支持

时间:2021-03-26 19:40:24

相关推荐

mfc工程中添加com接口支持

在普通的mfc工程中常常需要添加com接口支持.最典型的应用就是使用

com中的连接点机制时,需要在客户端实现事件接受器.简单说来,就是要实现在com服务器端声明的事件接口.这个接口由server端暴露给client,然后由client实现之,并在适当的时候由server端触发事件达到通知client的目的.这个过程就是连接点的回调.

支持IDispatch的接口,就是通常所说的双接口.支持IUnknown的接口通过vtbl来调用接口方法.vtbl是c++中类的内存结构形式,因而在vb,asp及各种script中只能通过组件暴露的IDispatch接口来调用接口方法.

以实现连接点为例,我们分别用上面所说的两种形式(客户端sink组件实现IDispatch接口以及不实现IDispatch接口)来说说在mfc工程中如何添加com接口支持.

1.sink组件不支持IDispatch

(1)Server:

在server端实现组件对事件回调的支持的步骤就不累述.这里说说关键地方在于,IDL文件需要这样修改几处:

library CONNECTIONCOMLib

{

importlib("stdole32.tlb");

importlib("stdole2.tlb");

[

uuid(AFE854B0-246F-4B66-B26F-A1060225C71C),

helpstring("_IxxxEvents Interface")

]

// Old block - take this out

// dispinterface _IxxxEvents

// {

// properties:

// methods:

// [id(1), helpstring("method ExecutionOver")]

// HRESULT ExecutionOver(intResult);

// };

//To this one -put this in

interface _Ixxxvents : IUnknown

{

[id(1), helpstring("method ExecutionOver")] HRESULT

ExecutionOver(intResult);

};

[

uuid(630B3CD3-DDB1-43CE-AD2F-4F57DC54D5D0),

helpstring("xxx Class")

]

coclass xxx

{

[default] interface Ixxx;

//[default, source] dispinterface _IxxxEvents; take this line

//out and put the line below in

[default, source] interface _IxxxEvents ;

};

};

目的是取消对IDispatch接口的支持.

在适当的地方添加Fire_xxx()即可触发client实现的事件函数.

(2)Client:

在client端添加一个新类,继承自_IxxxEvent,然后实现其成员函数:InterfaceQuery(),AddRef(),Release(),还有当然就是在server端定义的事件触发成员函数.

2.sink组件支持双接口.

mfc和atl中不一样.示例如下:

用ClassWizaed添加一个Automation类

.h中

class CProxyEvents : public CCmdTarget

{

DECLARE_DYNCREATE(CProxyEvents)

CProxyEvents(); // protected constructor used by dynamic creation

// Attributes

public:

void OnOption(VARIANT *Option);

void OnData(VARIANT *Data);

void OnError(int ErrorCode);

void OnConnectStatus(int ConnectStatus);

void OnErrorMessage(BSTR ErrorMessage);

void OnNews(BSTR News);

void OnKeepAlive(BSTR AckResponse);

HWND hwnd;

// Operations

public:

virtual ~CProxyEvents();

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CProxyEvents)

public:

virtual void OnFinalRelease();

//}}AFX_VIRTUAL

// Implementation

protected:

// Generated message map functions

//{{AFX_MSG(CProxyEvents)

// NOTE - the ClassWizard will add and remove member functions here.

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

// Generated OLE dispatch map functions

//{{AFX_DISPATCH(CProxyEvents)

// NOTE - the ClassWizard will add and remove member functions here.

//}}AFX_DISPATCH

DECLARE_DISPATCH_MAP()

DECLARE_INTERFACE_MAP()

};

.cpp中

BEGIN_MESSAGE_MAP(CProxyEvents, CCmdTarget)

//{{AFX_MSG_MAP(CProxyEvents)

// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(CProxyEvents, CCmdTarget)

DISP_FUNCTION_ID(CProxyEvents, "Option",8,OnOption, VT_EMPTY, VTS_PVARIANT)

DISP_FUNCTION_ID(CProxyEvents, "Data",2,OnData, VT_EMPTY, VTS_PVARIANT)

//[id(3), helpstring("method Error")] void Error(int ErrorCode);

DISP_FUNCTION_ID(CProxyEvents, "Error",3,OnError, VT_EMPTY, VTS_I4)

//[id(4), helpstring("method ConnectStatus")] void ConnectStatus(int ConnectStatus);

DISP_FUNCTION_ID(CProxyEvents, "ConnectStatus",4,OnConnectStatus, VT_EMPTY, VTS_I4)

//[id(5), helpstring("method ErrorMessage")] void ErrorMessage(BSTR ErrorMessage);

DISP_FUNCTION_ID(CProxyEvents, "ErrorMessage",5,OnErrorMessage, VT_EMPTY, VTS_BSTR)

//[id(6), helpstring("method News")] void News(BSTR News);

DISP_FUNCTION_ID(CProxyEvents, "News",6,OnNews, VT_EMPTY, VTS_BSTR)

//[id(7), helpstring("method KeepAlive")] void KeepAlive(BSTR AckResponse);

DISP_FUNCTION_ID(CProxyEvents, "KeepAlive",7,OnKeepAlive, VT_EMPTY, VTS_BSTR)

END_DISPATCH_MAP()

// Note: we add support for IID_IProxyEvents to support typesafe binding

// from VBA. This IID must match the GUID that is attached to the

// dispinterface in the .ODL file.

// {1F2E2D8A-7CE3-4BCA-A360-C66C46A86626}

BEGIN_INTERFACE_MAP(CProxyEvents, CCmdTarget)

INTERFACE_PART(CProxyEvents, DIID__IServerProxyEvents, Dispatch)

END_INTERFACE_MAP()

代码中用

LPUNKNOWN unknown=pProxyEvents->GetIDispatch(FALSE);

m_dwCookie=0;

int ret=AfxConnectionAdvise(m_ServerProxy, DIID__IServerProxyEvents, unknown, FALSE, &m_dwCookie);建立连接.

一般地,使一个mfc类支持IDispatch接口(添加自动化支持)可以通过以下步骤:

1.在CMyDialog的类声明中(即.h)加入

DECLARE_DISPATCH_MAP()

DECLARE_INTERFACE_MAP()

两个宏,再在源文件(.cpp)中添加

BEGIN_INTERFACE_MAP( CMyDialog, CDialog )

INTERFACE_PART( CMyDialog, IID_IDispatch, Dispatch )

END_INTERFACE_MAP()

BEGIN_DISPATCH_MAP( CMyDialog, CDialog )

//这里添加属性或方法

END_DISPATCH_MAP()

并在构造函数调用EnableAutomation();即可.在BEGIN_DISPATCH_MAP和END_DISPATCH_MAP宏之间加入想加的DISP_FUNCTION之类的宏以建立映射.如果觉得手动添加DISP_FUNCTION之类的宏麻烦,可如下修改即可使用ClassWizard来对这个类添加方法和属性了

在.cpp中

BEGIN_DISPATCH_MAP( CMyDialog, CDialog )

//{{AFX_DISPATCH_MAP( CMyDialog )

//}}AFX_DISPATCH_MAP

END_DISPATCH_MAP()

在.h中,在类声明中的任何一个地方加入

//{{AFX_DISPATCH( CMyDialog )

//}}AFX_DISPATCH

如上后就可通过ClassWizard来添加方法和属性了.

如果觉得《mfc工程中添加com接口支持》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。