免责声明:我不是 IDL(接口定义语言,用于定义 COM 类型的语言)或 Microsoft IDL 编译器 (MIDL) 方面的专家,但在玩弄了 scrrun 的类型库后,我得出了以下结论.dll,与枚举有类似的问题。其中一些信息是通过快速浏览这篇关于 IDL 和 VB6 的 DevX 文章收集的:IDL for VB Tutorial
VB6 期望实际的枚举有一个名称,而不仅仅是一个与名称对应的枚举typedef。该__MIDL___MIDL_itf_autosvcs_0469_0002名称是一个占位符,因为原始类型库没有在定义typedef枚举常量的位置定义枚举名称。
在 OLE Viewer 中查看类型库时,enum可能如下所示:
typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes;
typedef enum {
LockSetGet = 0,
LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;
第一个typedef创建公共名称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您在 OLE 查看器中查看类型库时看到的名称。编译器midl还会自动生成第二个typedef,将名称别名为typedef自动生成的enum名称。
问题是 VB6 无法理解以这种方式创建的枚举。它期望一切都在一个单一的typedef(即你给enum一个名字,以及命名typedef):
typedef enum LocksMode {
LockSetGet = 0,
LockMethod = 1
} LocksMode;
IDL 对待typedef' 的方式与 C 或 C++ 相同:您不必为枚举本身命名,因为typedef已经有名称,但如果您愿意,您可以为枚举命名。换句话说, thetypedef和 theenum实际上是两个独立的实体。VB6 碰巧将 thetypedef和 the识别enum为两个不同但相关性模糊的事物,因此在您的情况下,它会看到一个typedefnamed __MIDL___MIDL_itf_autosvcs_0469_0002,它会看到 this 是未命名枚举的别名,它还会看到typedeffor LockModes,这是另一个的公共别名typedef。
由于第一个typedef是公共的,您将LockModes在对象浏览器中看到一个条目,并且因为它是枚举的别名,您也会在对象浏览器中看到枚举常量。但是,实际的枚举本身没有名称(因此它会在浏览器中获得分配给它的时髦的自动生成名称),并且 VB6 不能使用该枚举,因为自动生成的名称在 VB6 中恰好是非法的(带有双下划线的名称在 VB6 中自动隐藏)。
为了证明最后一点,如果您在 VB6 代码中键入此内容,Intellisense 将工作并编译,但显然,它不是很理想:
MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod
此代码有效的原因是您可以将通常会导致语法错误的名称(例如以下划线开头的名称)放在括号中,以允许 VB6 接受通常非法的名称。此外,使用自动生成的名称为常量添加前缀适用于 Intellisense,因为它是enumVB6typedef与不能将所有部分放在一起以实现两个名称指的是相同的enum)。
除了像上面那样输入长得可笑的名称之外,您还可以enum通过在常量前面加上库名称来访问常量,例如,COMSVCSLib.LockMethod应该可以。我不太清楚为什么这实际上有效,而且我不确定如果两个不同enum的 ' 定义具有相同名称的常量会发生什么。
最后,您可以通过使用 OLE 查看器中的 IDL 创建自定义 IDL 文件以不同的方式解决此问题,在该文件中,您将现有的enumtypedefs 替换为一个单独typedef的 typedefs,每个enum只给出相同的名称enum和typedef相同的名称(即typedef enum LockModes { ... } LockModes;) ,但由于 OLE 查看器不一定生成有效的 IDL,因此您可能需要对其进行更多调整才能使其实际编译。如果您可以让它工作,那么您可以.tlb从您的 VB6 项目(而不是COMSVCSLib库)中引用您的自定义,并且enum's 将像您期望的那样工作。
如果你想走这条路,你还需要另外两个工具,它们应该已经安装在你的开发机器上(但你可能需要搜索它们):
midl.exe: 这个工具可以从一个文件中生成一个 typelib 文件 (*.tlb) .idl。因此,您可以将 IDL 从 OLE 查看器复制到记事本中,如上所述修改枚举定义,将其保存为.idl文件,然后将其传递midl.exe给以创建新的类型库:
midl my-custom-typelib.idl
regtlib.exe:此工具可以注册一个 .tlb 文件,如果您希望能够将其添加为对您的 VB6 项目的引用,则需要该文件:
regtlib.exe my-custom-typelib.tlb
然而,为此创建一个自定义类型库可能是多余的,并且如前所述,可能很难根据 OLE 查看器的输出获得可编译的 IDL 文件,因为它显示类型库的逆向工程 IDL,而不是原始 IDL。