【问题标题】:Reference to Window Object in VBA在 VBA 中引用窗口对象
【发布时间】:2015-07-26 23:52:12
【问题描述】:

我在 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

【问题讨论】:

  • 错误来自:Set winn = wins.Item(i)
  • 您是否尝试将wins.Item(i) 替换为wins(i)wins.Items(i)
  • 这两个建议也会抛出错误
  • 在 VBE 中观察“locals”窗口时,正确创建了 objShell 和 wins 对象。参考wins.count也很好用。 .item 属性在本地窗口中也可用。我不明白为什么它不起作用。

标签: vba excel


【解决方案1】:

这个界面有点奇怪,它似乎只适用于控制变量的副本,所以:

Set winn = wins.Item(i + 0)

Set winn = wins.Item((i))

【讨论】:

  • Item 期望 Variant 作为索引,并且后期绑定 VB 无法正确计算出来。这个技巧给了它一个轻推,同样将i 声明为变体。我相信正在发生一些 byref 传递,这会导致 byval。
  • 是的,问题已经解决了。所有解决方案都有效:在引用中添加 0,在引用中添加括号并将 i 声明为变体。这是非常奇怪/奇怪的问题。我们拥有 stackoverflow 社区真的是一件好事,为我节省了很多时间。感谢大家的支持!
【解决方案2】:

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

Item 方法接受 Variant 参数。

当调用接受 Variant 参数的外部方法时,VB 喜欢创建和传递通过引用提供值的 Variants - 即使用 VT_BYREF flag 集。
但是 VB 在发送中间结果(临时的,不存储在变量中)时并没有设置这个标志,这是有道理的,因为即使被调用的方法更新了值,也没有人能看到它。

因此,当您调用 .Item(i) 时,VB 发送一个类型为 VT_I4 | VT_BYREF 的 Variant,而当您调用 .Item(i + 0) 时,调度一个类型为 VT_I4 的 Variant,而没有 VT_BYREF

在大多数情况下,差异并不显着,因为 VARIANT-aware 方法应该能够处理任何一种情况。但是这个特定的方法does different things 取决于它接收到的VT_,因此它明确愿意拒绝除三个接受的VT_s 之外的任何VT_s。因此,为了调用它,您需要欺骗 VB 删除 byref 标志。

有趣的是,当您将变量声明为Variant 时,VB 仍会调度VT_VARIANT | VT_BYREF,但该方法似乎支持这种情况并正确解析为具有非引用类型@ 的指向内部Variant 987654341@.

注意这与VB的ByVal/ByRef无关——这是关于VARIANT data type的内部结构。

【讨论】:

  • quote "然而 VB 在发送中间结果(临时,不存储在变量中)时没有设置这个标志,这是有道理的,因为即使被调用的方法更新了值,也没有人能够看见了。”我不明白。在我的代码中,我使用 set 命令分配了一个变量:Set winn = wins.Item(i)。是括号之间的引用引起了问题,这是不合逻辑的。在表达式中放置一个操作“解决”了问题。正如您已经提到的,VB 做了不同的事情,结果相同。看起来需要一个变体!
  • 我说的是参数,不是返回值。 ian lvalue,而 i + 0(i)CLng(i)rvalues。当您调用Item(<lvalue>) 时,VB 会创建一个设置了VT_BYREF 的变体并将其传递给参数。当您调用Item(<rvalue>) 时,VB 会再次创建一个Variant 来传递参数,但不会设置VT_BYREF
  • 通常这并没有什么区别,但是这个特殊的方法Item(),如果设置了VT_BYREF,就会明确拒绝它的参数,因为它想根据在变体,不认为 VT_BYREF 是有效标志。
  • 我能理解一个表达式在记忆中创造活动。但是我不明白,为什么 i 是 Ivalue 而(i)是 Rvalue?不做任何操作,只做()。我可以理解 i+0 我们是一个右值,因为有一个操作完成。
  • 这是how VB operates,因为语言设计者是这样设计的。传递参数的默认方式是ByRef,对于ByRef,您需要您的数据类型完全匹配(您不能将Long 传递给VariantByRef)。通常它会阻止您编写简单的短代码(所有数据类型转换都由 VB 隐式完成),因此您可以使用括号将变量转换为表达式。请参阅 msdn.microsoft.com/en-us/library/aa263527%28VS.60%29.aspx,“通过引用传递参数”。
猜你喜欢
  • 2014-01-07
  • 1970-01-01
  • 2017-08-24
  • 2010-10-07
  • 2017-10-04
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多