代码之家  ›  专栏  ›  技术社区  ›  Binary Worrier

如何使用ATL创建VB6集合对象

  •  1
  • Binary Worrier  · 技术社区  · 16 年前

    或与vb6兼容的集合对象。

    我们通过一组API提供.NET产品的钩子。

    我们需要继续支持从vb6调用API的客户,因此我们需要继续支持vb6集合对象(在.NET中使用vba.collection很简单)。

    问题是支持一些使用vbscript调用我们的API的站点。vbscript没有集合对象的概念,因此为了创建一个要传递给我们的API的集合对象,我们构建了一个提供“createCollection”方法的vb6 ActiveX dll。此方法只创建并返回一个新的集合对象。问题解决了。

    经过多年的修剪、移植和重建,这个DLL是我们仅有的VB6代码。因此,我们仍然需要在开发和构建机器上安装Visual Studio 6。

    我不满意我们对这个DLL的依赖有几个原因(我个人对vb6的厌恶不是其中之一)。首先,微软不再支持Visual Studio 6。

    我的问题是,如何让ATL创建一个实现与VB6集合对象相同接口的集合对象。

    我对C++有很好的处理,但是只有对ATL的松散掌握,我可以创建简单的对象并实现简单的方法,但是这超出了我的能力。

    3 回复  |  直到 14 年前
        1
  •  8
  •   Georg Fritzsche    16 年前

    集合或多或少基于约定。它们实现 IDispatch 并公开一些标准方法和属性:

    • Add() - 可选择的
    • Remove() - 可选择的
    • Item()
    • Count - 只读的
    • _NewEnum - 隐藏的 , 只读的 ,返回指向实现的枚举器对象的指针 IEnumVariant

    这个 新纽 属性允许使用Visual Basic For Each .

    在IDL中使用 dual 接口和:

    • DISPID_VALUE 对于 项目()
    • [propget, id(DISPID_NEWENUM), restricted] HRESULT _NewEnum([out, retval] IUnknown** pVal)

    以下是一些msdn条目: Design Considerations for ActiveX Objects
    这里有一些ATL特有的便利: ATL Collections and Enumerators

        2
  •  2
  •   wqw    16 年前

    让我们以这个vbscript片段为目标

    Dim vElem
    For Each vElem In MyObject
        ...
    Next
    

    尤其是myObject的实现。至少,您必须在默认DispInterface(它的双/DispInterface用于讨论DispID)上实现一个具有DispID_NewEnum的方法/PropGet。你想叫什么就叫什么,没关系。大多数集合使用NewEnum,并在IDL中将其标记为隐藏。vb6使用下划线前缀来标记隐藏的方法,因此您可能会将newenum视为推荐,但它是一种货物崇拜ATL。

    不要 需要任何计数、项目、添加、删除、清除或任何其他方法(在默认接口上)。您可以提供这些作为一种便利(特别是项目访问器,可能还可以计数),但是您不必,这样就可以使上面的示例代码正常工作。

    下一步,重新评估 是一个单独的对象(称为枚举器),它通过使用指向myObject的(私有)指针来实现IEnumVariant接口。在IDL中,您可以声明retval为IUnknown,这里没有任何错误。最有趣的是你 为了只在ienumvariant上实现下一个方法,如果您喜欢或可选地实现它们,您可以在其余的方法上返回e_notimplemented,尽管它们从来没有被每个方法调用过。更容易实现的是next的celt参数(请求的项目数)是 总是 1,所以对于每个请求项,总是逐个进行。

    在ATL中可以使用ccomenumonstr等在STL容器上创建“代理”枚举器,或者基于数组的枚举器ATL提供(并排除STL)。

        3
  •  0
  •   Ruben Bartelink    14 年前

    有关如何实现脚本编程语言中自然使用的COM集合的好示例,请查看 my website

    它提供了一个如何做到这一点的综合示例…