在VBA中引用窗口对象

我有一个在VBA中引用一个Windows对象的问题。 它会抛出以下错误:“错误5(无效的过程调用或参数)我找不到原因,因为我看不到编程错误。

Public Sub TestWindowhandle() Dim lResult As Long Dim objShell, wins, winn Dim IE_Count As Long, i As Long, This_PID As Long On Error GoTo TestWindowhandle_Error Set objShell = CreateObject("Shell.Application") Set wins = objShell.Windows IE_Count = wins.Count For i = 0 To (IE_Count - 1) Set winn = wins.Item(i) Next i On Error GoTo 0 Exit Sub TestWindowhandle_Error: MsgBox "Error " & Err.Number & " (" & Err.Description & ") in line " & Erl & " in procedure TestWindowhandle of Module Module1" Stop End Sub 

有些奇怪的接口,它似乎只适用于控制variables的副本,所以:

 Set winn = wins.Item(i + 0) 

要么

 Set winn = wins.Item((i)) 

我相信这里正在发生的事情。

Item方法接受一个Variant参数。

当调用接受Variant参数的外部方法时,VB喜欢创build并传递通过引用提供值的变体,也就是说,在设置了VT_BYREF标志的情况下 。
但是,当发送中间结果(临时对象,不存储在variables中)时,VB不会设置这个标志,这是合理的,因为即使被调用的方法更新了值,也没有人能够看到它。

所以当你调用.Item(i) ,VB发出一个VT_I4 | VT_BYREFtypes的variables VT_I4 | VT_BYREF ,当你调用.Item(i + 0) ,调度VT_I4types的variables,而不VT_BYREF

在大多数情况下,差异并不重要,因为VARIANT意识的方法应该能够应付。 然而,这个特定的方法根据所接收的VT_来确定不同的事情 ,因此明确地愿意拒绝除三个可接受的VT_之外的任何VT_ 。 所以为了调用它,你需要欺骗VB去除byref标志。

有趣的是,当你声明variables为Variant ,VB仍然调度一个VT_VARIANT | VT_BYREF VT_VARIANT | VT_BYREF ,但该方法似乎支持这种情况,并正确地parsing到指向具有非引用types的VT_I4内部变式。

注意,这与VB的ByVal / ByRef无关 – 这是关于VARIANT数据types的内部结构。