向我的COM对象的VBScript用户公开一个事件处理程序 [英] Expose an event handler to VBScript users of my COM object

查看:218
本文介绍了向我的COM对象的VBScript用户公开一个事件处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I have a COM object which users can access via a call such as:

Set s = CreateObject("Server")

我想要做的是允许用户指定一个事件处理程序对象,像这样:

What I'd like to be able to do is allow the user to specify an event handler for the object, like so:

Function ServerEvent

   MsgBox "Event handled"

End Function

s.OnDoSomething = ServerEvent

可能的,如果是这样,我怎么暴露在我的类型库中的C ++(具体是BCB 2007)?

Is this possible and, if so, how do I expose this in my type library in C++ (specifically BCB 2007)?

推荐答案

我最近怎么做。向IDL添加实现IDispatch的接口和该接口的coclass:

This is how I did it just recently. Add an interface that implements IDispatch and a coclass for that interface to your 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类的声明:

This is the declaration of the CServerEvents class:

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接口和连接点映射的实现。 OnServerEvent方法的定义如下:

The key here is the implementation of the IConnectionPointImpl and IConnectionPointContainerImpl interfaces and the connection point map. The definition of the OnServerEvent method looks like this:

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或某事,但我更喜欢使处理程序的方法异步调用的参数。这样,用户只需要调用一个方法:

You need to provide a way for your client to specify their handler for your events. You can do this with a dedicated method like "SetHandler" or something, but I prefer to make the handler an argument to the method that is called asynchronously. This way, the user only has to call one method:

STDMETHOD(DoSomethingAsynchronous)( IServerEvents *pCallback );

存储指向IServerEvents的指针,然后当您想要触发事件时, :

Store the pointer to the IServerEvents, and then when you want to fire your event, just call the method:

m_pCallback->OnServerEvent();

对于VB代码,处理事件的语法与您建议的略有不同:

As for the VB code, the syntax for dealing with events is a little different than what you suggested:

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

我希望这有助于。

这篇关于向我的COM对象的VBScript用户公开一个事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆