除了“微软这么说”之外,还有更深的层次。您提出的错误编号是一个 32 位整数,因为这是 COM 规范的一部分,用于在组件之间传递错误。组件的所有公共方法实际上都是返回 HRESULT 作为返回值的函数;如果你有一个 VB 函数,它会秘密地将函数的返回值映射到一个 [out] 参数。HRESULT 值是一个由整堆值组成的位域;但为了简单起见,您可以将其分成两个 16 位部分。低 16 位包含实际的错误号,恰好在 0 到 65535 之间——无符号的 16 位范围。高 16 位有很多标准。最重要的是 0x0000____。所有使用这个的常量都以“S_”开头(代表成功)。最常用的 32 位值是 S_OK (0x00000000)。如果返回此值,则该函数已成功。大多数 VB 方法调用都会返回这个值。但是,任何设置了最高位的值都表明存在错误。在十六进制中,这些值看起来像 0x8___ 。有许多类别的错误。VB 默认返回的是 0x800A。然而,COM 规范只给你一个你可以正式使用的类,0x8004——它在 VB 中表示为常量 vbObjectError。
事实上,VB 建议您在 ActiveX DLL 或 EXE 中的公共方法引发错误时使用 vbObjectError 常量。你做不做都没有区别。这只是意味着调用代码收到的错误非常大且为负数,因此您必须将错误号与 &H0000FFFF 相加才能取回您的 16 位整数。有趣的是,它还建议你不要使用 ActiveX 控件方法执行此操作,可能是因为与 ActiveX 控件方法关联的高 16 位是 0x800A000。更有趣的是,当您默认引发错误时,VB 本身会将所有错误编号与 0x800A0000 进行“与”运算。同样,它会检测错误号是否类似于 0x800A____ - 如果是这样,无论如何都会为您删除高 16 位,因此您只需处理错误号本身。在我的工作场所,我们有许多 VB 组件。我们的标准是不使用 vbObjectError 或错误代码。这为我们省去了随后必须在调用代码中屏蔽它的麻烦。
例如,如果您有 COMPONENT1.CLASS1 和 COMPONENT2.CLASS2。CLASS1.Method1 调用 CLASS2.Method1。如果我在 CLASS2 中引发错误,那么我必须在 CLASS1.Method1 中处理它。按照微软的规定,我会这样写:
COMPONENT1.CLASS1
Function Method1()
On Error GoTo ErrorHandler
...
ErrorHandler:
If (Err.Number And vbObjectError) = vbObjectError Then
Select Case Err.Number And (Not vbObjectError)
Case Component2.EErrComponent2.ecBlahBlahError
... handle ...
End Select
End If
End Function
COMPONENT2.CLASS2
Enum EErrComponent2
ecBlahBlahError = 513 ' Minimum error code
End Enum
Function Method1()
...
Err.Raise EErrComponent1 Or vbObjectError
...
End Function
对多个组件重复此操作,此样板文件会有点令人厌烦,而且似乎实际上并没有给我们任何回报。
我们可能会这样做:
COMPONENT1.CLASS1
Function Method1()
On Error GoTo ErrorHandler
...
ErrorHandler:
Select Case Err.Number
Case Component2.EErrComponent2.ecBlahBlahError
... handle ...
End Select
End Function
COMPONENT2.CLASS2 枚举 EErrComponent2 ecBlahBlahError 结束枚举
Function Method1()
...
Err.Raise EErrComponent1
...
End Function
我想知道是否有人在不使用 vbObjectError 时遇到过问题。我们当然没有。