如何从C++;(ActiveX)到JavaScript 我遵循微软的教程,介绍如何实现C++的连接点和触发函数。问题是我无法使用正确的连接初始化IConnectionPointImpl::m_vec数组,因此m_vec.size=0

如何从C++;(ActiveX)到JavaScript 我遵循微软的教程,介绍如何实现C++的连接点和触发函数。问题是我无法使用正确的连接初始化IConnectionPointImpl::m_vec数组,因此m_vec.size=0,javascript,javascript-events,event-handling,activex,atl,Javascript,Javascript Events,Event Handling,Activex,Atl,在.IDL文件中,我声明了以下接口: [ uuid(F5219084-9D70-474A-8C05-46FFD1FCCC71), version(1.0), helpstring("BCPlayer 1.0 Type Library") ] library VPlayerLib { importlib("stdole2.tlb"); [ uuid(C4DFAB9A-435A-41A9-96B6-B23056DAA3FC),

在.IDL文件中,我声明了以下接口:

[
    uuid(F5219084-9D70-474A-8C05-46FFD1FCCC71),
    version(1.0),
    helpstring("BCPlayer 1.0 Type Library")
]
library VPlayerLib
{
    importlib("stdole2.tlb");
    [
        uuid(C4DFAB9A-435A-41A9-96B6-B23056DAA3FC),
        helpstring("_IVPlayerEvents Interface")
    ]
    dispinterface _IVPlayerEvents
    {
    properties:
    methods:
        [id(1)] HRESULT OnInfoCallback([in] BSTR pPlayerName, [in] BOOL bSuccessMsg, [in] LONG nCode, [in] HRESULT hrRet);
    };
...
...
稍后,使用Visual Studio的连接点向导创建了以下代理:

template<class T>
class CProxy_IVPlayerEvents :
    public ATL::IConnectionPointImpl<T, &__uuidof(_IVPlayerEvents)>
{
public:
    HRESULT Fire_OnInfoCallback(BSTR pPlayerName, BOOL bSuccessMsg, LONG nCode, HRESULT hrRet)
    {
        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[4];
                avarParams[3] = pPlayerName;
                avarParams[3].vt = VT_BSTR;
                avarParams[2] = bSuccessMsg;
                avarParams[2].vt = VT_BOOL;
                avarParams[1] = nCode;
                avarParams[1].vt = VT_I4;
                avarParams[0] = hrRet;
                avarParams[0].vt = VT_HRESULT;
                CComVariant varResult;

                DISPPARAMS params = { avarParams, NULL, 4, 0 };
                hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
            }
        }
        return hr;
    }
};
连接点地图:

BEGIN_CONNECTION_POINT_MAP(VPlayer)
    CONNECTION_POINT_ENTRY(__uuidof(_IVPlayerEvents))
END_CONNECTION_POINT_MAP() 
在javascript中,我尝试使用attachEvent和addEventListener进行绑定,而第一个尝试向m_vec添加了4个连接,但在销毁CComvaraint的过程中导致内存损坏:

avarParams[3] = pPlayerName;
avarParams[3].vt = VT_BSTR;
而addEventListener没有更改::m_vec并将其保持为零大小。在查看MSDN之后,我意识到addEventListener是绑定IE9及以上版本回调的首选方法

事件绑定的JavaScript代码:

function OnInfoCallback(){
    var a = arguments[0];
    var b = arguments[1];
    var c = arguments[2];
    var d = arguments[3];
    alert("here");
}
...
...

player.addEventListener("OnInfoCallback", OnInfoCallback, false);

感谢您的帮助

您找到了实现此功能的方法吗?事实上,我找到了,我没有使用任何连接点,只是创建了一个setter函数,该函数接收IDispatch*并将其存储到一个CComPtr中,然后使用InvokeN()调用回调。
avarParams[3] = pPlayerName;
avarParams[3].vt = VT_BSTR;
function OnInfoCallback(){
    var a = arguments[0];
    var b = arguments[1];
    var c = arguments[2];
    var d = arguments[3];
    alert("here");
}
...
...

player.addEventListener("OnInfoCallback", OnInfoCallback, false);