gpt4 book ai didi

events - 向我的 COM 对象的 VBScript 用户公开事件处理程序

转载 作者:行者123 更新时间:2023-12-04 07:48:11 25 4
gpt4 key购买 nike

假设我有一个 COM 对象,用户可以通过如下调用访问它:

Set s = CreateObject("Server")

我想做的是允许用户为对象指定一个事件处理程序,如下所示:
Function ServerEvent

MsgBox "Event handled"

End Function

s.OnDoSomething = ServerEvent

这是否可能,如果可以,我如何在 C++(特别是 BCB 2007)的类型库中公开它?

最佳答案

这就是我最近的做法。将实现 IDispatch 的接口(interface)和该接口(interface)的 coclass 添加到 IDL:

[
object,
uuid(6EDA5438-0915-4183-841D-D3F0AEDFA466),
nonextensible,
oleautomation,
pointer_default(unique)
]
interface IServerEvents : IDispatch
{
[id(1)]
HRESULT OnServerEvent();
}

//...

[
uuid(FA8F24B3-1751-4D44-8258-D649B6529494),
]
coclass ServerEvents
{
[default] interface IServerEvents;
[default, source] dispinterface IServerEvents;
};

这是 CServerEvents 类的声明:
class ATL_NO_VTABLE CServerEvents :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CServerEvents, &CLSID_ServerEvents>,
public IDispatchImpl<IServerEvents, &IID_IServerEvents , &LIBID_YourLibrary, -1, -1>,
public IConnectionPointContainerImpl<CServerEvents>,
public IConnectionPointImpl<CServerEvents,&__uuidof(IServerEvents)>
{
public:
CServerEvents()
{
}

// ...

BEGIN_COM_MAP(CServerEvents)
COM_INTERFACE_ENTRY(IServerEvents)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CServerEvents)
CONNECTION_POINT_ENTRY(__uuidof(IServerEvents))
END_CONNECTION_POINT_MAP()

// ..

// IServerEvents
STDMETHOD(OnServerEvent)();

private:
CRITICAL_SECTION m_csLock;
};

这里的关键是 IConnectionPointImpl 和 IConnectionPointContainerImpl 接口(interface)和连接点映射的实现。 OnServerEvent 方法的定义如下所示:
STDMETHODIMP CServerEvents::OnServerEvent()
{
::EnterCriticalSection( &m_csLock );

IUnknown* pUnknown;

for ( unsigned i = 0; ( pUnknown = m_vec.GetAt( i ) ) != NULL; ++i )
{
CComPtr<IDispatch> spDisp;
pUnknown->QueryInterface( &spDisp );

if ( spDisp )
{
spDisp.Invoke0( CComBSTR( L"OnServerEvent" ) );
}
}

::LeaveCriticalSection( &m_csLock );

return S_OK;
}

您需要为您的客户提供一种方法来为您的事件指定他们的处理程序。您可以使用诸如“SetHandler”之类的专用方法来执行此操作,但我更喜欢将处理程序作为异步调用的方法的参数。这样,用户只需调用一个方法:
STDMETHOD(DoSomethingAsynchronous)( IServerEvents *pCallback );

存储指向 IServerEvents 的指针,然后当您想要触发事件时,只需调用该方法:
m_pCallback->OnServerEvent();

至于 VB 代码,处理事件的语法与您建议的略有不同:
Private m_server As Server
Private WithEvents m_serverEvents As ServerEvents

Private Sub MainMethod()
Set s = CreateObject("Server")
Set m_serverEvents = New ServerEvents

Call m_searchService.DoSomethingAsynchronous(m_serverEvents)
End Sub

Private Sub m_serverEvents_OnServerEvent()
MsgBox "Event handled"
End Sub

我希望这有帮助。

关于events - 向我的 COM 对象的 VBScript 用户公开事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com