代码之家  ›  专栏  ›  技术社区  ›  Ken Smith

在JavaScript中处理ATL/ActiveX事件

  •  2
  • Ken Smith  · 技术社区  · 14 年前

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

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

    here . 我现在有了一个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;
     }
    };
    

    (3) 我在代码的适当位置(在主UI线程上)调用Fire\u 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 回复  |  直到 14 年前
        1
  •  3
  •   Ken Smith    14 年前

    我通过查看VS2010附带的Circ示例项目就知道了这一点。结果(至少在我的例子中)ATL事件向导没有更新dispatch接口的IDL。当我更新IDL文件的dispinterface部分时,生活很美好:

    dispinterface _IMyControlEvents
    {
        properties:
        methods:
    };
    

    对此:

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

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

        2
  •  0
  •   Mike Ellery    14 年前

    首先,我从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>
    
    推荐文章