function load transparent PNG picture into userform

KalilMe

Active Member
Joined
Mar 5, 2021
Messages
343
Office Version
  1. 2016
Platform
  1. Windows
hi experts

I hope finding solution for this question. it doesn't seem possible after searching for long time , who knows may be some professionals in this foum have answering
so this function load png pictur but I search for load transparent PNG picture if I have transparent PNG in my PC and load on userform it will change the backcolor to balack color . how can I get rid of the black color and load transparent picture as is existed in my PC?
VBA Code:
Option Explicit
Private Type GUID
    Data1                   As Long
    Data2                   As Integer
    Data3                   As Integer
    Data4(0 To 7)           As Byte
End Type

Private Type PICTDESC
    Size                        As Long
    Type                        As Long
    hPic                        As Long
    hPal                        As Long
End Type

Private Type GdiplusStartupInput
    GdiplusVersion              As Long
    DebugEventCallback          As Long
    SuppressBackgroundThread    As Long
    SuppressExternalCodecs      As Long
End Type

Private Declare Function GdiplusStartup Lib "GDIPlus" (token As Long, _
    inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As Long, bitmap As Long) As Long
Private Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As Long, _
    hbmReturn As Long, ByVal background As Long) As Long
Private Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal image As Long) As Long
Private Declare Function GdiplusShutdown Lib "GDIPlus" (ByVal token As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As PICTDESC, _
    RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long

Public Function LoadImage(ByVal strFName As String) As IPicture
    Dim uGdiInput As GdiplusStartupInput
    Dim hGdiPlus As Long
    Dim hGdiImage As Long
    Dim hBitmap As Long

    uGdiInput.GdiplusVersion = 1
    
    If GdiplusStartup(hGdiPlus, uGdiInput) = 0 Then
        If GdipCreateBitmapFromFile(StrPtr(strFName), hGdiImage) = 0 Then
            GdipCreateHBITMAPFromBitmap hGdiImage, hBitmap, 0
            Set LoadImage = ConvertToIPicture(hBitmap)
            GdipDisposeImage hGdiImage
        End If
        GdiplusShutdown hGdiPlus
    End If

End Function

Public Function ConvertToIPicture(ByVal hPic As Long) As IPicture

    Dim uPicInfo As PICTDESC
    Dim IID_IDispatch As GUID
    Dim IPic As IPicture

    Const PICTYPE_BITMAP = 1

    With IID_IDispatch
        .Data1 = &H7BF80980
        .Data2 = &HBF32
        .Data3 = &H101A
        .Data4(0) = &H8B
        .Data4(1) = &HBB
        .Data4(2) = &H0
        .Data4(3) = &HAA
        .Data4(4) = &H0
        .Data4(5) = &H30
        .Data4(6) = &HC
        .Data4(7) = &HAB
    End With

    With uPicInfo
        .Size = Len(uPicInfo)
        .Type = PICTYPE_BITMAP
        .hPic = hPic
        .hPal = 0
    End With

    OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic

    Set ConvertToIPicture = IPic
End Function
 
thanks guys for your trying to help me . but truly I no know what's the problem
based on post #8 this is what I got
ا1.PNG



and based on post #8 this is what i got
2.PNG

may you guess where is my mistake?
 
Upvote 0

Excel Facts

Last used cell?
Press Ctrl+End to move to what Excel thinks is the last used cell.
@KalilMe Prompted by the point made by @Jaafar Tribak, I have looked at your issue, and have recreated the userform/frame/ control arrangement you used.

It is important to remember the instructions I set out on how to call the function:
The slight change means that you now need to also tell VBA the background colour of the container form/control. So when you want to load a transparent PNG file as a picture for the Userform, you could add the following to the UserForm:
Here is the example i referenced:
VBA Code:
Me.Picture = LoadImage("D:\FolderName\ImageName.PNG", Me.BackColor)
I repeat, you must add the background colour that you want to replace the transparency with.

When I recreated your scenario and called the function in accordance with the instructions above, this is the result:

1638407936801.png


The image on the left is a result of the code at reply#8, and the the right from the code at reply#9. They are identical. To do this, I called the function exactly as I explained above. Alternatively, you could expressly reference the RGB colour code (which is RGB 0, 120, 215)):
VBA Code:
Me.Picture = LoadImage("D:\FolderName\ImageName.PNG", RGB(0, 120, 215))

Please let us know how it goes.
 
Upvote 0
@Jaafar Tribak
call function by command button
VBA Code:
Private Sub CommandButton1_Click()

    Dim vntFilename As Variant
    
    vntFilename = Application.GetOpenFilename("Images (*.png),*.png")
    If vntFilename = "False" Then Exit Sub
    
    Frame1.Picture = LoadPNGImage(vntFilename)

End Sub
 
Upvote 0
Ok, well thank you for sending that through. I think the problem is pretty clear. Have you had a chance to read the instructions?
 
Upvote 0
I repeat, you must add the background colour that you want to replace the transparency with.
I' m really sorry about it
Me.Picture = LoadImage("D:\FolderName\ImageName.PNG", Me.BackColor)
perfect choice . I changed to this
VBA Code:
Private Sub CommandButton1_Click()

    Dim vntFilename As Variant
 
    vntFilename = Application.GetOpenFilename("Images (*.png),*.png")
    If vntFilename = "False" Then Exit Sub
 
    Image1.Picture = LoadImage((vntFilename), Me.BackColor)


End Sub
it works perfectly
many thanks @Dan_W & @Jaafar Tribak (y)
 
Last edited:
Upvote 0
That's perfectly ok - I'm relieved to hear that it's working, because otherwise I would have run out of ideas! :rolleyes:
Thanks to @Jaafar Tribak for his guidance, otherwise we may have encountered a few more issues in getting the colour situation resolved.

Thank you also for marking it as being solved - I hope that this comes in handy for anyone else who might need it.
 
Upvote 0
Just for grins, here is a more compact function with some added error handling.

Some usage examples:
VBA Code:
    Me.Picture = LoadPNGImage("D:\ie12.png")
    Me.Frame1.Picture = LoadPNGImage("D:\ie12.png", Me.Frame1.BackColor)
    Me.Label1.Picture = LoadPNGImage("D:\ie12.png", vbRed)


In a Standard Module:
VBA Code:
Option Explicit

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

Private Type PICTDESC
    size As Long
    Type As Long
    #If Win64 Then
        hPic As LongLong
        hPal As LongLong
    #Else
        hPic As Long
        hPal As Long
    #End If
End Type

Private Type GdiplusStartupInput
    GdiplusVersion As Long
    #If Win64 Then
        DebugEventCallback As LongLong
    #Else
        DebugEventCallback As Long
    #End If
    SuppressBackgroundThread As Long
    SuppressExternalCodecs As Long
End Type

#If VBA7 Then
    Private Declare PtrSafe Function TranslateColor Lib "oleAut32.dll" Alias "OleTranslateColor" (ByVal clr As OLE_COLOR, ByVal palet As LongPtr, Col As Long) As Long
    Private Declare PtrSafe Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
    'Windows API calls into the GDI+ library
    Private Declare PtrSafe Function GdiplusStartup Lib "gdiplus" (token As LongPtr, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As LongPtr = 0) As Long
    Private Declare PtrSafe Function GdipCreateBitmapFromFile Lib "gdiplus" (ByVal FILENAME As LongPtr, BITMAP As LongPtr) As Long
    Private Declare PtrSafe Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal BITMAP As LongPtr, hbmReturn As LongPtr, ByVal background As LongPtr) As Long
    Private Declare PtrSafe Function GdipDisposeImage Lib "gdiplus" (ByVal Image As LongPtr) As Long
    Private Declare PtrSafe Sub GdiplusShutdown Lib "gdiplus" (ByVal token As LongPtr)
    Private Declare PtrSafe Function OleCreatePictureIndirect Lib "oleaut32" (PicDesc As PICTDESC, RefIID As GUID, ByVal fPictureOwnsHandle As Long, iPic As IPicture) As Long
#Else
    Private Declare Function TranslateColor Lib "oleAut32.dll" Alias "OleTranslateColor" (ByVal clr As OLE_COLOR, ByVal palet As Long, Col As Long) As Long
    Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
    'Windows API calls into the GDI+ library
    Private Declare Function GdiplusStartup Lib "GDIPlus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
    Private Declare Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As Long, bitmap As Long) As Long
    Private Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As Long
    Private Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal image As Long) As Long
    Private Declare Sub GdiplusShutdown Lib "GDIPlus" (ByVal token As Long)
    Private Declare Function OleCreatePictureIndirect Lib "oleaut32" (PicDesc As PICTDESC, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
#End If


Public Function LoadPNGImage(ByVal sFileName As String, Optional ByVal PNGBackColor As Variant) As IPicture

    Const PICTYPE_BITMAP = 1
    Const COLOR_BTNFACE = 15

    #If Win64 Then
        Dim hToken As LongLong, hBMP As LongLong, hGdiBmp As LongLong
    #Else
        Dim hToken As Long, hBMP As Long, hGdiBmp As Long
    #End If

    Dim uGdiInput As GdiplusStartupInput
    Dim uPicinfo As PICTDESC, IID_IDispatch As GUID
    Dim sErrMsg As String, sFuncCall As String
    Dim lRGB As Long, lBGR As Long
    Dim lRet As Long

    uGdiInput.GdiplusVersion = 1
 
    lRet = GdiplusStartup(hToken, uGdiInput)
    If lRet Then
        sFuncCall = "'GdiplusStartup'"
        GoTo Xit
    End If
 
    lRet = GdipCreateBitmapFromFile(StrPtr(sFileName), hBMP)
    If lRet Then
        sFuncCall = "'GdipCreateBitmapFromFile'"
        GoTo Xit
    End If
 
   If IsMissing(PNGBackColor) Then
       PNGBackColor = GetSysColor(COLOR_BTNFACE)
   End If
 
    lRet = TranslateColor(PNGBackColor, 0, lRGB)
    If lRet Then
        sFuncCall = "'TranslateColor'"
        GoTo Xit
    End If
 
    lBGR = RGB((lRGB \ 65536) Mod 256, (lRGB \ 256) Mod 256, (lRGB Mod 256))
 
    lRet = GdipCreateHBITMAPFromBitmap(hBMP, hGdiBmp, lBGR)
    If lRet Then
        sFuncCall = "'GdipCreateHBITMAPFromBitmap'"
        GoTo Xit
    End If
 
    With IID_IDispatch
        .Data1 = &H20400
        .Data4(0) = &HC0
        .Data4(7) = &H46
    End With
    With uPicinfo
        .size = Len(uPicinfo)
        .Type = PICTYPE_BITMAP
        .hPic = hGdiBmp
    End With
    lRet = OleCreatePictureIndirect(uPicinfo, IID_IDispatch, True, LoadPNGImage)
    If lRet Then
        sFuncCall = "'OleCreatePictureIndirect'"
        GoTo Xit
    End If

Xit:

    If hBMP Then
        Call GdipDisposeImage(hBMP)
    End If
    If hToken Then
        Call GdiplusShutdown(hToken)
    End If

    If lRet Then
        sErrMsg = "Error: "
        Select Case lRet
            Case 1
                sErrMsg = sErrMsg & "#GenericError"
            Case 2
                sErrMsg = sErrMsg & "#InvalidParameter"
            Case 3
                sErrMsg = sErrMsg & "#OutOfMemory"
            Case 4
                sErrMsg = sErrMsg & "#objectBusy"
            Case 5
                sErrMsg = sErrMsg & "#InsufficientBuffer"
            Case 6
                sErrMsg = sErrMsg & "#NotImplemented"
            Case 7
                sErrMsg = sErrMsg & "#Win32Error"
            Case 8
                sErrMsg = sErrMsg & "#WrongState"
            Case 9
                sErrMsg = sErrMsg & "#Aborted"
            Case 10
                sErrMsg = sErrMsg & "#FileNotFound"
            Case 11
                sErrMsg = sErrMsg & "#ValueOverflow"
            Case 12
                sErrMsg = sErrMsg & "#AccessDenied"
            Case 13
                sErrMsg = sErrMsg & "#UnknownImageFormat"
            Case 14
                sErrMsg = sErrMsg & "#FontFamilyNotFound"
            Case 15
                sErrMsg = sErrMsg & "#FontStyleNotFound"
            Case 16
                sErrMsg = sErrMsg & "#NotTrueTypeFont"
            Case 17
                sErrMsg = sErrMsg & "#UnsupportedGdiplusVersion"
            Case 18
                sErrMsg = sErrMsg & "#GdiplusNotInitialized"
            Case 19
                sErrMsg = sErrMsg & "#PropertyNotFound"
            Case 20
                sErrMsg = sErrMsg & "#PropertyNotSupported"
            Case 21
                sErrMsg = sErrMsg & "#ProfileNotFound"
        End Select
     
        MsgBox sErrMsg & vbNewLine & vbNewLine & "Call: " & sFuncCall
 
    End If

End Function
Hi Jaafar, Mark here again (I did visit your SO profile:). Please find attached my workbook to try out the above code. It's not working (or doesn't appear to be working), could you take a look for me and tell me where I'm going wrong? Not sure how I upload a workbook but here's my code (it should work as I just copied yours!). Thanks and regards, Mark

I have a button on a worksheet to show the form: LoadTransparentImageTest.Show

I have a standard module into which I copied your main code.

I have a form named: LoadTransparentImageTest

On the form I have an image control named Image 1

Behind the form I have the initialisation code:


Private Sub UserForm_Initialize()

Dim ImageLocation As String
ImageLocation = "C:\SectorBtn.png"

Me.Image1.Picture = LoadImage(ImageLocation)

End Sub


Also tried it with a frame, still no luck.Perhaps I could email you the workbook?

Thanks and regards, Mark
 
Upvote 0
Please disregard my post, I set the PictureSizeMode to Zoom and there's my button in all it's glory, thank you very much for the code which will allow me to make my app look very pretty and have buttons with rounded corners (Isn't VBA amazing at getting round MS's shortcomings, why didn't they just make it so you could load images natively eh?).

Thanks (again) and regards, Mark
 
Upvote 0

Forum statistics

Threads
1,215,219
Messages
6,123,687
Members
449,117
Latest member
Aaagu

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top