从JavaScript中处理ATL / ActiveX事件

时间:2010-08-26 22:08:25

标签: c++ events activex atl

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

(1)我告诉ATL实现IProviderClassInfo2接口,如here所述。

(2)我按照here的指示在我的ATL项目中实现了连接点。我现在有一个CProxy_IMyControlEvents类,具有相应的Fire_Authenticated(),Fire_Connected()和Fire_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;
 }
};

(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>

(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>

我已经准备好了我可以在互联网上找到的关于如何做到这一点的一切,而且我似乎并没有遗漏任何东西。所以我必须做一些愚蠢的事情。关于我可能做错什么或如何解决问题的任何建议?

2 个答案:

答案 0 :(得分:3)

我通过查看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();
};

一旦我这样做,我就能够使用各种不同的事件处理语法。

答案 1 :(得分:0)

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

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

<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>