I have a problem referencing a windows object in VBA. it throws the following error: "Error 5 (Invalid procedure call or argument). I cannot find the cause, because I see no programming error.
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
Something odd with that interface, it seems to only work with a copy of the control variable so:
or
I believe here is what is happening.
The
Item
method accepts aVariant
parameter.When calling an external method that accepts a Variant parameter, VB likes to create and pass Variants that provide the value by reference - that is, with the
VT_BYREF
flag set.However VB does not set this flag when sending out intermediate results (temporaries, not stored in a variable), which makes sense because even if the called method updates the value, no one will be able to see it.
So when you call
.Item(i)
, VB sends out a Variant of typeVT_I4 | VT_BYREF
, and when you call.Item(i + 0)
, a Variant of typeVT_I4
is dispatched, without theVT_BYREF
.In most situations the difference is not significant because VARIANT-aware methods should be able to cope with either. However this particular method does different things depending on exactly which
VT_
it receives, and because of this it is explicitly willing to reject anyVT_
s other than the three accepted ones. So in order to call it you need to trick VB into removing the byref flag.Interestingly, when you declare the variable as
Variant
, VB still dispatches aVT_VARIANT | VT_BYREF
, but the method seems to support this situation and correctly resolves to the pointed-to inner Variant that has the non-reference type ofVT_I4
.Note this has nothing to do with VB's
ByVal
/ByRef
- this is about the internal structure of theVARIANT
data type.