That code uses the Interface Identifier (IID) for the IPicture interface. An IID happens to be of GUID type, so it can cause some confusion leading to poor and further misleading code like that shown above.

That code is even worse in a way because it unnecessarily copies the Byte array before using it, chewing up extra memory and CPU cycles.

I'd use this instead:

Code:
Private Const READ_ALL As Long = 0
Private Const WIN32_FALSE As Long = 0

Private Type IID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

Private Declare Function CLSIDFromString Lib "ole32" ( _
    ByVal lpsz As Long, _
    ByRef clsid As IID) As Long
Private Declare Function OleLoadPicture Lib "oleaut32" ( _
    ByVal Stream As IUnknown, _
    ByVal lSize As Long, _
    ByVal fRunmode As Long, _
    ByRef riid As IID, _
    ByRef Picture As IPicture) As Long
Private Declare Function SHCreateMemStream Lib "shlwapi" Alias "#12" ( _
    ByRef Init As Byte, _
    ByVal cbInit As Long) As IUnknown

Private Function LoadPictureBytes(ByRef Bytes() As Byte) As IPicture
    Dim Count As Long
    Dim Stream As IUnknown
    Dim IID_IPicture As IID

    Count = UBound(Bytes) - LBound(Bytes) + 1
    If Count < 1 Then Exit Function
    Set Stream = SHCreateMemStream(Bytes(LBound(Bytes)), Count)
    If Not (Stream Is Nothing) Then
        CLSIDFromString StrPtr("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"), IID_IPicture
        OleLoadPicture Stream, READ_ALL, WIN32_FALSE, IID_IPicture, LoadPictureBytes
    End If
End Function
But it is essentially the same thing without the clumsy overhead. If you call it multiple times it would help to assign IID_IPicture once before calling the LoadPictureBytes() function.


If you want to know what OleLoadPicture() does you can look it up in your MSDN Library Help. Every legal copy of VB6 Pro and Enterprise came with the online Help and Samples on CDs. You can also find it at OleLoadPicture function (olectl.h).


OleLoadPicture() returns an object reference upon success. The object is a StdPicture but you need to tell it which public interface you want a pointer to. That is why the reference to interface identifier (riid, a pointer to an IID) is needed.

There are two: IPicture and IPictureDisp. So we pick one since we don't care in VB6 because when we need to query for another interface that gets handled for us through coercion behind the scenes.

VB6 does a lot of things like that for us, either emitting code or calls into the runtime to coerce data. But once we try to creep below the covers by making explicit API calls we have to be a lot more careful and handle more details.