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

C++ 如何使用ATL创建VB6集合对象,c++,vb6,atl,compatibility,C++,Vb6,Atl,Compatibility,或VB6兼容的集合对象 我们通过一组API向.net产品提供挂钩 我们需要继续支持从VB6调用API的客户,因此我们需要继续支持VB6集合对象(在.net中使用VBA.collection很简单) 问题是支持一些使用VBScript调用API的站点。VBScript没有集合对象的概念,所以为了创建一个集合对象来传递给我们的API,我们构建了一个VB6 ActiveX DLL,它提供了一个“CreateCollection”方法。此方法仅创建并传回一个新的集合对象。问题解决了 经过多年的修剪、移植

或VB6兼容的集合对象

我们通过一组API向.net产品提供挂钩

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

问题是支持一些使用VBScript调用API的站点。VBScript没有集合对象的概念,所以为了创建一个集合对象来传递给我们的API,我们构建了一个VB6 ActiveX DLL,它提供了一个“CreateCollection”方法。此方法仅创建并传回一个新的集合对象。问题解决了

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

我不喜欢我们依赖这个DLL有几个原因(我个人不喜欢VB6不是其中之一)。最重要的是微软不再支持VisualStudio6

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


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

集合或多或少都是基于惯例的。它们实现了IDispatch,并公开了一些标准方法和属性:

  • Add()
    -可选
  • Remove()
    -可选
  • Item()
  • 计数
    -只读
  • \u NewEnum
    -隐藏,只读,返回指向实现
\u NewEnum
属性是允许Visual Basic
对每个
执行操作的属性

在IDL中,您使用一个
接口,并:

  • Item()的
    DISPID\u值
  • [propget,id(DISPID_NEWENUM),restricted]HRESULT_NEWENUM([out,retval]IUnknown**pVal)
以下是一些MSDN条目:

这里有一些ATL特有的便利:

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

Dim vElem
For Each vElem In MyObject
    ...
Next
特别是MyObject的实现。作为最低要求,您必须在默认dispinterface(其dual/dispinterface用于谈论DISPID)上使用DISPID_NEWENUM实现一个方法/propget。你可以随便给它取名字,没关系。大多数集合使用NewEnum,并在IDL中将其标记为隐藏。VB6使用下划线前缀来标记隐藏的方法,因此您可能会将_NewEnum视为建议,但它有点像ATL所做的货物崇拜

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

接下来,retval必须是一个单独的对象(所谓的枚举器),它通过使用指向MyObject的(私有)指针实现IEnumVARIANT接口。在IDL中,您可以将retval声明为IUnknown,此处没有任何错误。最有趣的是,您只需要在IEnumVARIANT上实现下一个方法,如果您愿意,您可以在其余的方法上返回E_NOTIMPLEMENTED,或者可以选择实现它们,尽管它们从未被每个方法调用。使实现更容易的是Next的celt参数(请求的项目数)始终为1,因此对于每个请求,项目总是一个接一个


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

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


它提供了一个全面的例子,说明了如何做到这一点……

您不需要对每一个都进行计数等,但可能会破坏使用它们的其他代码。MSDN还说它必须命名为_NewEnum-虽然这对于VB6来说可能不是必需的,但它可能会破坏其他代码。。。我已经看到了CComEnumOnSTL对象和ATL集合对象。这是一个“被宠坏的选择”,我不知道该选择哪一个。有什么建议可以用来在ATL中构建集合对象,并将其传递给需要VB6集合的VB6函数吗?@gf:Active Directory对象是支持枚举而不公开项/计数的类的一个示例。我不确定他们在转到最后一个元素之前是否知道计数。听起来这个VB6 DLL很少更改。您真的需要经常构建它吗?我的想法是不再支持VB6 IDE,而是支持VB6运行时。如果你不需要构建DLL,IDE不受支持是一个大问题吗?我知道你的意思,但是我们有法律义务构建我们所有的代码。我们不能拥有无法构建的非第三方组件。VB6中的“强类型”集合仍然通过IEnumVARIANT枚举。强制转换是隐式完成的(可能会失败)。