C++ 从JavaScript中处理ATL/ActiveX事件

C++ 从JavaScript中处理ATL/ActiveX事件,c++,events,activex,atl,C++,Events,Activex,Atl,我有一个ATL ActiveX控件,它会引发三个事件(已连接、已验证、已断开连接),这些事件需要在IE/JavaScript中处理。据我所知,我做的每件事都是对的,特别是: (1) 我已经告诉ATL实现IProviderClassInfo 2接口,如前所述 (2) 我已经按照说明在ATL项目中实现了连接点。我现在有了一个CProxy\u IMyControlEvents类,它具有适当的Fire\u Authenticated()、Fire\u Connected()和Fire\u Disconn

我有一个ATL ActiveX控件,它会引发三个事件(已连接、已验证、已断开连接),这些事件需要在IE/JavaScript中处理。据我所知,我做的每件事都是对的,特别是:

(1) 我已经告诉ATL实现IProviderClassInfo 2接口,如前所述

(2) 我已经按照说明在ATL项目中实现了连接点。我现在有了一个CProxy\u IMyControlEvents类,它具有适当的Fire\u Authenticated()、Fire\u Connected()和Fire\u Disconnected()实现。它们看起来或多或少像这样:

template<class T>
class CProxy_IVncServerControlEvents :
 public ATL::IConnectionPointImpl<T, &__uuidof(_IVncServerControlEvents)>
{
public:
HRESULT Fire_Connected()
 {
  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 varResult;

    DISPPARAMS params = { NULL, NULL, 0, 0 };
    hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,  &params, &varResult, NULL, NULL);
   }
  }
  return hr;
 }
};
模板
CProxy\U IVncServerControlEvents类:
公共ATL::IConnectionPointImpl
{
公众:
HRESULT Fire_Connected()
{
HRESULT hr=S_正常;
T*pThis=静态施法(本);
int cConnections=m_vec.GetSize();
对于(int-iConnection=0;iConnectionLock();
CComPtr punkConnection=m_vec.GetAt(iConnection);
p此->解锁();
IDispatch*p连接=静态_转换(punkConnection.p);
if(pConnection)
{
变异结果;
DISPPARAMS params={NULL,NULL,0,0};
hr=pConnection->Invoke(1,IID\u NULL,LOCALE\u USER\u DEFAULT,DISPATCH\u METHOD,¶ms,&varResult,NULL,NULL);
}
}
返回人力资源;
}
};
(3) 我在代码中的适当位置(在主UI线程上)调用Fire_Connected()等,调试器确认它们正在触发

(4) 我正在一个HTML页面中实例化生成的控件,并且能够调用该控件上的方法。这些方法执行它们应该执行的操作,并成功返回

<object id="MyControl" classid="CLSID:42832F4C-3480-4450-A6B5-156B2EFC408F" codebase="http://localhost:51150/Resources/MyControlInstaller.CAB" />

<script language="javascript">
var myControl = document.getElementById("MyControl");
myControl.connect();
</script>

var myControl=document.getElementById(“myControl”);
myControl.connect();
(5) 我正在将事件连接到JavaScript函数处理程序。这似乎是我遇到麻烦的地方。我见过三种不同的方法,它们似乎都不适合我

<!-- Method #1 -->
<script language="javascript">
myControl.attachEvent('Connected', onConnected);
myControl.attachEvent('Disconnected', onDisconnected);
myControl.attachEvent('Authenticated', onAuthenticated);
</script>

<!-- Method #2 -->
<script language="javascript">
myControl.Connected = onConnected;
myControl.Disconnected = onDisconnected;
myControl.Authenticated = onAuthenticated;
</script>

<!-- Method #3 -->
<script for="MyControl" language="javascript">
function MyControl::Connected()
{
    onConnected();
}

function MyControl::Disconnected()
{
    onDisconnected();
}

function MyControl::Authenticated()
{
    onAuthenticated();
}
</script>

myControl.attachEvent(“已连接”,未连接);
myControl.attachEvent(“断开”,或“断开”);
myControl.attachEvent(“已验证”,经验证);
myControl.Connected=未连接;
myControl.Disconnected=onDisconnected;
myControl.Authenticated=onAuthenticated;
函数MyControl::Connected()
{
未连接();
}
函数MyControl::Disconnected()
{
onDisconnected();
}
函数MyControl::Authenticated()
{
onAuthenticated();
}

我已经准备好了在互联网上找到的关于如何做到这一点的一切,而且我似乎没有遗漏任何东西。所以我一定是在做傻事。关于我可能做错了什么或如何排除故障,有什么建议吗?

首先,我从MSDN看到的所有示例都使用“JScript”作为语言,而不是“javascript”,但我不知道这是否有区别(也许两者都被接受,但从技术上讲,我相信MS的ECMA实现是JScript)

作为方法3的变体,可以尝试为脚本指定事件属性:

<script for="MyControl" EVENT="Connected()" language="JScript">
  onConnected();
</script>

<script for="MyControl" EVENT="Disconnected()" language="JScript">
  onDisconnected();
</script>

<script for="MyControl" EVENT="Authenticated()" language="JScript">
  onAuthenticated();
</script>

未连接();
onDisconnected();
onAuthenticated();

我通过查看VS2010附带的Circ示例项目找到了答案。事实证明(至少在我的例子中)ATL事件向导没有更新分派接口的IDL。当我从以下内容更新IDL文件的dispinterface部分时,生活很好:

dispinterface _IMyControlEvents
{
    properties:
    methods:
};
为此:

dispinterface _IMyControlEvents
{
    properties:
    methods:
        [id(1)] void Connected();
        [id(2)] void Disconnected();
        [id(3)] void Authenticated();
};

一旦我这样做了,我就能够让各种不同的事件处理语法发挥作用。

谢谢你的建议。不幸的是,我试过了,但事件仍然没有发生。继续环顾四周…在JS事件中处理未通过标记集成到DOM的COM对象是否很热?例如,这是JS从
windows.external
接收的对象,依此类推。。。