Results 1 to 4 of 4

Thread: How to use GUID in VB6?

  1. #1

    Thread Starter
    Junior Member
    Join Date
    May 2021
    Posts
    16

    How to use GUID in VB6?

    Hello. I was looking for how to convert image to byte array, and i found this https://www.vbforums.com/showthread....-on-Picturebox. It works on my case, but i have no idea why is the code like that, what is GUID, and why i must use that. Can i use the identifier randomly? i need an explanation for this code. i've tried to googled it but still can't understand. Here's the code.

    Code:
    Private Function ArrayToPicture(inArray() As Byte, Offset As Long, Size As Long) As IPicture
        ' function creates a stdPicture from the passed array
        ' Offset is first item in array: 0 for 0 bound arrays
        ' Size is how many bytes comprise the image
        Dim o_hMem  As Long
        Dim o_lpMem  As Long
        Dim aGUID(0 To 3) As Long
        Dim IIStream As IUnknown
    
        aGUID(0) = &H7BF80980    ' GUID for stdPicture
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
    
        o_hMem = GlobalAlloc(&H2&, Size)
        If Not o_hMem = 0& Then
            o_lpMem = GlobalLock(o_hMem)
            If Not o_lpMem = 0& Then
                CopyMemory ByVal o_lpMem, inArray(Offset), Size
                Call GlobalUnlock(o_hMem)
                If CreateStreamOnHGlobal(o_hMem, 1&, IIStream) = 0& Then
                      Call OleLoadPicture(ByVal ObjPtr(IIStream), 0&, 0&, aGUID(0), ArrayToPicture)
                End If
            End If
        End If
    End Function

    I use it with this code

    Code:
    Public Function Base64Encode(vArr As Variant) As String
        Const Routine As String = "Base64.Base64Encode"
        Dim xmlDoc As Object
        Dim xmlNode As Object
        
        Set xmlDoc = CreateObject("MSXML2.DOMDocument")
        
        Set xmlNode = xmlDoc.createElement("b64")
        
        xmlNode.DataType = "bin.base64"
        xmlNode.nodeTypedValue = vArr
        
        Base64Encode = xmlNode.Text
        
    End Function

  2. #2
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: How to use GUID in VB6?

    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.

  3. #3
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: How to use GUID in VB6?

    This code gives me the willies:

    Code:
    Public Function Base64Encode(vArr As Variant) As String
        Const Routine As String = "Base64.Base64Encode"
        Dim xmlDoc As Object
        Dim xmlNode As Object
        
        Set xmlDoc = CreateObject("MSXML2.DOMDocument")
        
        Set xmlNode = xmlDoc.createElement("b64")
        
        xmlNode.DataType = "bin.base64"
        xmlNode.nodeTypedValue = vArr
        
        Base64Encode = xmlNode.Text
        
    End Function
    Why are you late binding those MSXML2 objects?

    Why are you passing vArr As Variant? As far as I can tell that code will only work in the case where you pass a Byte array, so why not make it type safe and declare it like:

    Code:
    Public Function Base64Encode(ByRef Bytes() As Byte) As String

    Just like the previous code above, it works... with warts... as long as you hold your mouth right and cross your fingers.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    May 2021
    Posts
    16

    Re: How to use GUID in VB6?

    dilettante, sorry I take a long time to responded to it. Many thanks for your code and example. I use the base64 encoding method to process this picture. i use the previous program that i asked for an explanation. It succeeded, but is there any other method to process the jpeg picture? actually I will send the data in the radio module that needs a binary input.


    Quote Originally Posted by dilettante View Post
    This code gives me the willies:

    Code:
    Public Function Base64Encode(vArr As Variant) As String
        Const Routine As String = "Base64.Base64Encode"
        Dim xmlDoc As Object
        Dim xmlNode As Object
        
        Set xmlDoc = CreateObject("MSXML2.DOMDocument")
        
        Set xmlNode = xmlDoc.createElement("b64")
        
        xmlNode.DataType = "bin.base64"
        xmlNode.nodeTypedValue = vArr
        
        Base64Encode = xmlNode.Text
        
    End Function
    Why are you late binding those MSXML2 objects?

    Why are you passing vArr As Variant? As far as I can tell that code will only work in the case where you pass a Byte array, so why not make it type safe and declare it like:

    Code:
    Public Function Base64Encode(ByRef Bytes() As Byte) As String

    Just like the previous code above, it works... with warts... as long as you hold your mouth right and cross your fingers.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width