vb6 - 为什么 TypeLib 枚举不在 Visual Basic 6.0 中公开为枚举?

标签 vb6 enums constants typelib

我有一个引用 COMSVCSLib 的 VB6 项目,其中一种方法调用 COMSVCSLib 的 SharedPropertyGroupManager.CreatePropertyGroup 传递 锁定方法 进程作为参数。

清理 VB6 代码:

Dim groupName       As String
Dim spmMgr          As COMSVCSLib.SharedPropertyGroupManager
Dim spmGroup        As COMSVCSLib.SharedPropertyGroup

Dim bGroupExists    As Boolean

Set spmMgr = New COMSVCSLib.SharedPropertyGroupManager

With spmMgr
    Set spmGroup = .CreatePropertyGroup(groupName, LockMethod, Process, bGroupExists)

End With

几年来没有使用 VB6,起初我认为 LockMethod 和 Process 是在项目中其他地方定义的变量或常量。

在对对象浏览器进行了一些研究后,我发现它们都在 COMSVCSLib 中作为常量公开。

Object Browser

但是在 OLE/COM 对象查看器中查看它们的定义,它们似乎被定义为枚举值:
typedef enum {
    LockSetGet = 0,
    LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;

为什么来自 COMSVCSLib 的 IDL/TypeLib 枚举不作为枚举公开给 Visual Basic 6.0?

最佳答案

免责声明 :我不是 IDL(接口(interface)定义语言,它是用于定义 COM 类型的语言)或 Microsoft IDL 编译器 (MIDL) 的专家,但在玩弄 scrrun 的类型库后,我得出了以下结论。 dll,它与枚举有类似的问题。从快速浏览这篇关于 IDL 和 VB6 的 DevX 文章中收集到的一些信息:IDL for VB Tutorial

VB6 期望实际的枚举具有名称,而不仅仅是 typedef 的枚举。想要一个名字。 __MIDL___MIDL_itf_autosvcs_0469_0002 name 是一个占位符,因为原始类型库没有在同一个 typedef 中定义枚举名称。其中定义了枚举常量。

当您在 OLE 查看器中查看类型库时,enum大概是这样的:

typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes;

typedef enum {
    LockSetGet = 0,
    LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;

第一typedef创建公共(public)名称 LockModes作为自动生成 MIDL___MIDL_itf_autosvcs_0469_0002 的别名enum 的名称.编译原始类型库时,midl编译器生成了长 __MIDL原名enum并自动创建了一个 typedef别名指向它。

最初的 IDL 可能像这样定义了枚举:
typedef enum {
     LockSetGet = 0,
     LockMethod = 1
} LockModes;

midl编译器处理 enum以这种方式编写的定义,它会自动为 enum 生成一个名称。 (因为它丢失了 - 它应该出现在 enum 关键字之后)。这是什么__MIDL name 是您在 OLE 查看器中查看类型库时看到的名称。 midl编译器还会自动生成第二个 typedef别名 typedef自动生成的名称 enum姓名。

问题是 VB6 无法理解以这种方式创建的枚举。它希望所有内容都集中在一个 typedef 中(即你给 enum 一个名字,以及命名 typedef ):
typedef enum LocksMode {
    LockSetGet = 0,
    LockMethod = 1
} LocksMode;

IDL 款待 typedef与 C 或 C++ 的方式相同:您不必为枚举本身命名,因为 typedef已经有一个名字,但如果你愿意,你可以给枚举一个名字。换句话说,typedefenum实际上是两个独立的实体。 VB6 恰好能识别 typedefenum因为是两个不同但关联模糊的事物,所以在您的情况下,它会看到 typedef命名 __MIDL___MIDL_itf_autosvcs_0469_0002 ,它看到这是一个未命名枚举的别名,它也看到了 typedefLockModes ,这是另一个 typedef 的公共(public)别名.

自第一期typedef是公开的,您将看到 LockModes 的条目在对象浏览器中,并且因为它是枚举的别名,您还将在对象浏览器中看到枚举常量。但是,实际的枚举本身没有名称(因此它会在浏览器中获得分配给它的时髦的自动生成的名称),并且 VB6 无法使用该枚举,因为自动生成的名称在 VB6 中恰好是非法的(带有双下划线的名称在 VB6 中自动隐藏)。

为了证明最后一点,如果你在你的 VB6 代码中输入这个,Intellisense 将工作并且它会编译,但显然,它不是很理想:
MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod

这段代码有效的原因是因为您可以将通常会导致语法错误的名称(例如以下划线开头的名称)放在方括号中,以允许 VB6 接受通常非法的名称。此外,使用自动生成的名称作为常量前缀适用于 Intellisense,因为它是 VB6 与 enum 关联的实际名称。 (记住另一个 typedef 只是这个“真实”的别名,但自动生成的名称,VB6 显然不能把所有的部分放在一起来实现这两个名称指的是同一个 enum )。

除了像上面那样输入长得可笑的名字,您还可以访问 enum以库名作为前缀来定义常量,例如,COMSVCSLib.LockMethod应该管用。我不太清楚为什么这实际上有效,而且我不确定如果两个不同的 enum 会发生什么情况's 定义具有相同名称的常量。

最后,您可以通过使用 OLE 查看器中的 IDL 创建自定义 IDL 文件以不同的方式解决此问题,您可以在其中替换现有的 enum。带有单个 typedef 的 typedef每个enum这只是给出了 enumtypedef相同的名称(即 typedef enum LockModes { ... } LockModes; ),但由于 OLE 查看器不一定生成有效的 IDL,因此您可能需要对其进行更多调整才能使其实际编译。如果你可以让它工作,那么你可以引用你的自定义 .tlb来自您的 VB6 项目(而不是 COMSVCSLib 库)和 enum 's 将像您期望的那样工作。

如果你想走这条路,你需要另外两个工具,它们应该已经安装在你的开发机器上(但你可能需要搜索它们):
  • midl.exe : 这个工具可以从 .idl 生成一个 typelib 文件 (*.tlb)文件。因此,您可以将 IDL 从 OLE 查看器复制到记事本中,如上所述修改枚举定义,将其保存为 .idl文件,并将其传递给 midl.exe制作一个新的类型库:
    midl my-custom-typelib.idl
  • regtlib.exe :此工具可以注册一个 .tlb 文件,如果您希望能够将其添加为对 VB6 项目的引用,则需要该文件:
    regtlib.exe my-custom-typelib.tlb

  • 但是,为此创建自定义类型库可能有点过头了,并且如前所述,可能很难根据 OLE 查看器的输出获得可编译的 IDL 文件,因为它显示的是类型库的逆向工程 IDL,而不是原始IDL。

    关于vb6 - 为什么 TypeLib 枚举不在 Visual Basic 6.0 中公开为枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3764124/

    相关文章:

    web-services - API设计: How should distinct classes of errors be handled from an asynchronous XMLHTTP call?

    php - 如何通过连接声明 PHP 类常量?

    java - 如何将输入定向到常量?

    c++ - 构造函数中的 Const 参数导致 stackoverflow

    ide - 如何避免在 Visual Basic 6 中自动重命名子签名参数

    VB.NET 如何让 1 个子应用到多个项目?

    vb6 - Post 方法 + WinHttpRequest + multipart/form-data

    Java 将扫描器输入与 ENUM 进行比较

    c++ - 删除重复的枚举元素

    c++ - 为什么在前向声明时必须提供枚举的大小?