|
|
|
IEnumVARIANT Interface |
|
IID_IEnumVARIANT |
{00020404-0000-0000-C000-000000000046} |
|
The IEnumVARIANT interface provides a method for enumerating a collection of variants, including heterogeneous collections of objects and intrinsic types. Callers of this interface do not need to know the specific type (or types) of the elements in the collection.
|
|
Methods in VTable order |
|
|
IUnknown Methods |
Description |
|
QueryInterface |
Returns pointers to supported interfaces. |
|
AddRef |
Increments reference count. |
|
Release |
Decrements reference count. |
|
IEnumVARIANT Methods |
Description |
|
Next |
Gets the next items in the enumeration sequence. |
|
Skip |
Attempts to skip over the next celt elements in the enumeration sequence. |
|
Reset |
Resets the enumeration sequence to the beginning. |
|
Clone |
Creates a copy of the current state of enumeration. |
|
Next |
|
FUNCTION IEnumVARIANT_Next ( _ BYVAL pthis AS DWORD PTR _ , BYVAL celt AS DWORD _ , BYVAL rgelt AS DWORD _ , BYREF pceltFetched AS DWORD _
) AS
LONG
LOCAL HRESULT AS LONG END FUNCTION
|
|
Skip |
|
FUNCTION IEnumVARIANT_Skip ( _ BYVAL pthis AS DWORD PTR _ , BYVAL celt AS DWORD _
) AS LONG
LOCAL HRESULT AS LONG END FUNCTION
|
|
Reset |
|
FUNCTION IEnumVARIANT_Reset ( _ BYVAL pthis AS DWORD PTR _
) AS LONG
LOCAL HRESULT
AS LONG END FUNCTION
|
|
Clone |
|
FUNCTION IEnumVARIANT_Clone ( _ BYVAL pthis AS DWORD PTR _ , BYVAL ppenum AS DWORD _
) AS LONG
LOCAL HRESULT
AS LONG END FUNCTION
|
|
Collection's Enumerator |
|
Enumerates a collection and returns its contents in an array of variants. Collections can be enumerated using the Item property of the interfaces, but in many cases, it expects a key instead of am index. In the case of the FileSystemObject, to enumerate the Files collection you will need to pass the name of a file to get a reference that allows to get the name of this file! In such a situation, we need a generic enumerator, such the ForEach function of Visual Basic. The following wrapper functions provide access to the IEnumVARIANT interface, and an example of how to use it.
|
|
' *********************************************************************************************
' ENUMERATOR
' *********************************************************************************************
' Enumerates a collection and returns its contents in an array of variants.
' This is a generic enumerator, so you don't need to select any typelib to generate it.
' Collections are in general enumerated using the Item property of the interfaces, but in
' many cases, it expects a key instead of am index. In the case of the FileSystemObject, to
' enumerate the Files collection you will need to pass the name of a file to get a reference
' that allows to get the name of this file! In such a situation, we need a generic enumerator,
' such the ForEach function of Visual Basic. The following wrapper functions provide access to
' the IEnumVARIANT interface, and an example of how to use it.
' *********************************************************************************************
' ********************************************************************************************
' EXCEPINFO structure
' ********************************************************************************************
TYPE TB_Collection_EXCEPINFO
wCode AS WORD ' An error code describing the error.
wReserved AS WORD ' Reserved
bstrSource AS DWORD ' Source of the exception.
bstrDescription AS DWORD ' Textual description of the error.
bstrHelpFile AS DWORD ' Help file path.
dwHelpContext AS DWORD ' Help context ID.
pvReserved AS DWORD ' Reserved.
pfnDeferredFillIn AS DWORD ' Pointer to function that fills in Help and description info.
scode AS DWORD ' An error code describing the error.
END TYPE
' ********************************************************************************************
' ********************************************************************************************
' Returns a pointer to a specified interface on an object to which a client currently holds an
' interface pointer. This function must call IUnknown_AddRef on the pointer it returns.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_QueryInterface (BYVAL pthis AS DWORD PTR, BYREF riid AS GUID, BYREF ppvObj AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[0] USING TB_Collection_IUnknown_QueryInterface(pthis, riid, ppvObj) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' ********************************************************************************************
' ********************************************************************************************
' The IUnknown::AddRef method increments the reference count for an interface on an object. It
' should be called for every new copy of a pointer to an interface on a given object.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_AddRef (BYVAL pthis AS DWORD PTR) AS DWORD
LOCAL DWRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[1] USING TB_Collection_IUnknown_AddRef(pthis) TO DWRESULT
FUNCTION = DWRESULT
END FUNCTION
' ********************************************************************************************
' ********************************************************************************************
' Decrements the reference count for the calling interface on a object. If the reference count
' on the object falls to 0, the object is freed from memory.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_Release (BYVAL pthis AS DWORD PTR) AS DWORD
LOCAL DWRESULT AS DWORD
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[2] USING TB_Collection_IUnknown_Release(pthis) TO DWRESULT
FUNCTION = DWRESULT
END FUNCTION
' ********************************************************************************************
' ********************************************************************************************
' Provides access to properties and methods exposed by an object.
' ********************************************************************************************
FUNCTION TB_Collection_IDispatch_Invoke (BYVAL pthis AS DWORD PTR, BYVAL dispidMember AS LONG, BYREF riid AS GUID, _
BYVAL lcid AS DWORD, BYVAL wFlags AS WORD, BYREF pdispparams AS DISPPARAMS, BYREF pvarResult AS VARIANT, _
BYREF pexcepinfo AS TB_Collection_EXCEPINFO, BYREF puArgErr AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[6] USING TB_Collection_IDispatch_Invoke(pthis, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' ********************************************************************************************
' *********************************************************************************************
' HRESULT Next([in] UI4 celt, [in] *VARIANT rgvar, [out] *UI4 pceltFetched)
' The Next method enumerates the next celt elements in the enumerator's list, returning them in
' rgelt along with the actual number of enumerated elements in pceltFetched.
' Parameters:
' celt
' [in] Number of items in the array.
' rgelt
' [out] Address of array containing items.
' pceltFetched
' [out] Address of variable containing actual number of items.
' Return Value:
' Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Next (BYVAL pthis AS DWORD PTR, BYVAL celt AS DWORD, BYVAL rgelt AS DWORD, BYREF pceltFetched AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[3] USING TB_Collection_IEnumVARIANT_Next(pthis, celt, rgelt, pceltFetched) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************
' *********************************************************************************************
' HRESULT Skip([in] UI4 celt)
' The Skip method Instructs the enumerator to skip the next celt elements in the enumeration so
' the next call to TB_Collection_IEnumVARIANT_Next does not return those elements.
' Parameter:
' celt
' [in] Number of items to skip.
' Return Value:
' Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Skip (BYVAL pthis AS DWORD PTR, BYVAL celt AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[4] USING TB_Collection_IEnumVARIANT_Skip(pthis, celt) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************
' *********************************************************************************************
' HRESULT Reset()
' The Reset method instructs the enumerator to position itself at the beginning of the list
' of elements.
' Return Value:
' Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Reset (BYVAL pthis AS DWORD PTR) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[5] USING TB_Collection_IEnumVARIANT_Reset(pthis) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************
' *********************************************************************************************
' HRESULT Clone([out] **IEnumVARIANT ppenum)
' The Clone method creates another items enumerator with the same state as the current
' enumerator to iterate over the same list. This method makes it possible to record a point in
' the enumeration sequence in order to return to that point at a later time.
' Parameters:
' ppenum
' [out] Address of a variable that receives the IEnumVARIANT interface pointer.
' Return Value:
' Returns %S_OK if the method succeeds.
' Remarks
' The caller must release the new enumerator separately from the first enumerator.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Clone (BYVAL pthis AS DWORD PTR, BYVAL ppenum AS DWORD) AS LONG
LOCAL HRESULT AS LONG
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
CALL DWORD @@pthis[6] USING TB_Collection_IEnumVARIANT_Clone(pthis, ppenum) TO HRESULT
FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************
' ********************************************************************************************
' _NewEnum method [Restricted]
' Member identifier: -4 (_NewEnum always has a DispID of -4)
' Returns a a reference to the IUnknown interface of a collection.
' Notes: Some objects declare it as a method and others as a property, so we are passing
' both flags, %DISPATH_METHOD (=1) and %DISPATCH_PROPERTYGET (=2) = 1 OR 2.
' The _NewEnum property can have a different VTable offset for each collection. Since we want
' a generic function, we have to call Invoke taking advantage of the fact that _NewEnum has
' always a DispID of -4.
' ********************************************************************************************
FUNCTION TB_Collection_NewEnum (BYVAL pthis AS DWORD, BYREF ppenum AS DWORD) AS DWORD
DIM IID_NULL AS GUID
DIM uDispParams AS DISPPARAMS
DIM vResult AS VARIANT
DIM puArgErr AS DWORD
ppenum = 0
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
FUNCTION = TB_Collection_IDispatch_Invoke (pthis, -4, IID_NULL, 0, 1 OR 2, uDispParams, vResult, BYVAL 0, puArgErr)
ppenum = VARIANT#(vResult)
IF ISTRUE ppenum THEN TB_Collection_IUnknown_AddRef ppenum ' increment the reference counter
END FUNCTION
' ********************************************************************************************
' *********************************************************************************************
' Returns the number of objects of the collection.
' Provides the same functionality as the Count property of the object.
' *********************************************************************************************
FUNCTION TB_Collection_Count (BYVAL pthis AS DWORD) AS LONG
LOCAL HRESULT AS LONG ' // COM result code
LOCAL IID_IEnumVariant AS GUID ' // GUID of the IEnumVARIANT interface
LOCAL pEnum AS DWORD ' // Address of a pointer to the collection
LOCAL pIEnumVARIANT AS DWORD ' // Address of a pointer to the IEnumVARIANT interface
LOCAL nCount AS LONG ' // Number of elements in the collection
LOCAL celtFetched AS DWORD ' // Number of elements fetched
LOCAL dwArray AS DWORD ' // Pointer to the first element in the array
LOCAL vVar AS VARIANT ' // General purpose variant
IID_IEnumVARIANT = GUID$("{00020404-0000-0000-c000-000000000046}")
' Check for null pointer
IF ISFALSE pthis THEN EXIT FUNCTION
' Get a reference to the Enumerator object
HRESULT = TB_Collection_NewEnum (pthis, pEnum)
IF ISTRUE HRESULT OR ISFALSE pEnum THEN EXIT FUNCTION
' Get a pointer to the IEnumVARIANT interface.
HRESULT = TB_Collection_IUnknown_QueryInterface (pEnum, IID_IEnumVARIANT, pIEnumVARIANT)
IF ISTRUE HRESULT OR ISFALSE pIEnumVARIANT THEN
TB_Collection_IUnknown_Release pEnum
EXIT FUNCTION
END IF
' Release the collection's enumerator interface.
' Note: If pEnum and pIEnumVARIANT are the same, this will decrease the reference count;
' otherwise, it will release the enumerator interface.
TB_Collection_IUnknown_Release pEnum
' Position the enumerator at the beginning of the list
HRESULT = TB_Collection_IEnumVARIANT_Reset(pIEnumVARIANT)
IF ISTRUE HRESULT THEN
TB_Collection_IUnknown_Release pIEnumVARIANT
EXIT FUNCTION
END IF
' Parses the collection
DO
' Fetch an element of the collection
HRESULT = TB_Collection_IEnumVARIANT_Next (pIEnumVARIANT, 1, BYVAL VARPTR(vVar), celtFetched)
IF ISTRUE HRESULT OR celtFetched < 1 THEN EXIT DO
nCount = nCount + 1
LOOP
' Release the interface
TB_Collection_IUnknown_Release pIEnumVARIANT
' Return the number of objects retrieved
FUNCTION = nCount
END FUNCTION
' *********************************************************************************************
' *********************************************************************************************
' TB_EnumCollection
' *********************************************************************************************
' - Helper function to enumerate collectios. Returns an array of pointers to objects.
' This provides similar functionality to the Visual Basic's ForEach function.
' We need it to enumerate collections than expect a key instead of an index.
' It is also much faster to enumerate an entire collection using this method that using
' the Item property, that should be reserved to get a single object of the collection.
' Parameters:
' pthis = Pointer to the interface whose collection we want to enumerate.
' vArray = Dimensioned array of variants.
' Return Value:
' An HRESULT (&H80004003 = %E_POINTER) or error 461 (array not dimensioned)
' Example:
' The code below demonstrates the use of the enumerator with the FileSystemObject.
'
' #DIM ALL
' #DEBUG ERROR ON
' #INCLUDE "win32api.inc"
' #INCLUDE "TB_ENUM.inc"
'
' FUNCTION PBMAIN
'
' ' -------------------------------------------------------------------------
' ' ** STARTUP **
' ' -------------------------------------------------------------------------
' ' Create an instance of the object.
' ' -------------------------------------------------------------------------
' LOCAL oFso AS DISPATCH
' SET oFso = NEW DISPATCH IN "Scripting.FileSystemObject"
' IF ISFALSE ISOBJECT(oFso) THEN EXIT FUNCTION
' ' -------------------------------------------------------------------------
'
' ' --------------------------------------------------------------------------
' ' Get a reference to the Folder object
' ' --------------------------------------------------------------------------
' LOCAL oFolder AS DISPATCH
' LOCAL vFolder AS VARIANT
' LOCAL vPath AS VARIANT
' vPath = "c:\pbwin70\bin\"
'
' OBJECT CALL oFso.GetFolder(vPath) TO vFolder
' SET oFolder = vFolder
' ' --------------------------------------------------------------------------
'
' ' --------------------------------------------------------------------------
' ' Get a reference to the Files collection
' ' --------------------------------------------------------------------------
' LOCAL oFiles AS DISPATCH
' LOCAL vFiles AS VARIANT
' OBJECT GET oFolder.Files TO vFiles
' SET oFiles = vFiles
' ' --------------------------------------------------------------------------
'
' ' --------------------------------------------------------------------------
' ' Release the Folder interface
' ' --------------------------------------------------------------------------
' SET oFolder = NOTHING
'
' ' --------------------------------------------------------------------------
' ' Get the number of files
' ' --------------------------------------------------------------------------
' LOCAL vFilesCount AS VARIANT
' LOCAL nCount AS LONG
' OBJECT GET oFiles.Count TO vFilesCount
' nCount = VARIANT#(vFilesCount)
' ' --------------------------------------------------------------------------
'
' ' --------------------------------------------------------------------------
' ' Enumerate the Files collection
' ' --------------------------------------------------------------------------
' LOCAL oItem AS DISPATCH
' LOCAL i AS LONG
' LOCAL vName AS VARIANT
' LOCAL vRes AS VARIANT
'
' DIM vArray (1 TO nCount) AS VARIANT ' // DIM an array of variants
' TB_EnumCollection(OBJPTR(oFiles), vArray()) ' // Enumerate the collection
'
' FOR i = LBOUND(vArray) TO UBOUND(vArray)
' SET oItem = vArray(i) ' // Assign the interface reference
' IF OBJRESULT THEN EXIT FOR ' // Exit on failure
' vName = EMPTY ' // Empty the variant
' OBJECT GET oItem.Name TO vName ' // Get the name of the file
' PRINT VARIANT$(vName) ' // Show it
' SET oItem = NOTHING ' // Release the interface
' NEXT
'
' ' -------------------------------------------------------------------------
' ' ** CLEANUP **
' ' -------------------------------------------------------------------------
' SET oFiles = NOTHING ' Release the Files interface
' SET oFso = NOTHING ' Release the FileSystemObject object
'
' WAITKEY$
'
' END FUNCTION
'
' *********************************************************************************************
FUNCTION TB_EnumCollection (BYVAL pthis AS DWORD, vArray() AS VARIANT) AS LONG
LOCAL HRESULT AS LONG ' // COM result code
LOCAL IID_IEnumVariant AS GUID ' // GUID of the IEnumVARIANT interface
LOCAL pEnum AS DWORD ' // Address of a pointer to the collection
LOCAL pIEnumVARIANT AS DWORD ' // Address of a pointer to the IEnumVARIANT interface
LOCAL nCount AS LONG ' // Number of elements to fetch
LOCAL celtFetched AS DWORD ' // Number of elements fetched
LOCAL dwArray AS DWORD ' // Pointer to the first element in the array
LOCAL vVar AS VARIANT ' // General purpose variant
IID_IEnumVARIANT = GUID$("{00020404-0000-0000-c000-000000000046}")
' Check for null pointer
IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION ' %E_POINTER
' Number of elements in the array
nCount = ARRAYATTR(vArray(), 4)
IF nCount = 0 THEN FUNCTION = 461 : EXIT FUNCTION ' Array not dimensioned
' Get a reference to the Enumerator object
HRESULT = TB_Collection_NewEnum (pthis, pEnum)
IF ISTRUE HRESULT THEN FUNCTION = HRESULT : EXIT FUNCTION
IF ISFALSE pEnum THEN FUNCTION = &H80004003 : EXIT FUNCTION
' Get a pointer to the IEnumVARIANT interface.
HRESULT = TB_Collection_IUnknown_QueryInterface (pEnum, IID_IEnumVARIANT, pIEnumVARIANT)
IF ISTRUE HRESULT THEN
FUNCTION = HRESULT
TB_Collection_IUnknown_Release pEnum
EXIT FUNCTION
END IF
IF ISFALSE pIEnumVARIANT THEN
FUNCTION = &H80004003
TB_Collection_IUnknown_Release pEnum
EXIT FUNCTION
END IF
' Release the collection's enumerator interface.
' Note: If pEnum and pIEnumVARIANT are the same, this will decrease the reference count;
' otherwise, it will release the enumerator interface.
TB_Collection_IUnknown_Release pEnum
' Position the enumerator at the beginning of the list of elements
HRESULT = TB_Collection_IEnumVARIANT_Reset (pIEnumVARIANT)
IF ISTRUE HRESULT THEN
FUNCTION = HRESULT
TB_Collection_IUnknown_Release pIEnumVARIANT
EXIT FUNCTION
END IF
' Fetch nCount elements of the collection
dwArray = VARPTR(vArray(LBOUND(vArray)))
HRESULT = TB_Collection_IEnumVARIANT_Next (pIEnumVARIANT, nCount, dwArray, celtFetched)
FUNCTION = HRESULT
' Release the interface
TB_Collection_IUnknown_Release pIEnumVARIANT
END FUNCTION
' *********************************************************************************************
|
Page last updated on Thursday, 16 March 2006 19:57:55 +0100