Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1531

[VB6] Another Method for Loading/Drawing PNG

$
0
0
I've known about this method for quite some time and even use it in some of my projects. But haven't seen it applied elsewhere. So, I thought I'd make it more known with an example.

We know there are plenty of examples of loading a PNG file. Those typically use GDI+, WIA, or a custom control. However, since Vista, we can do this with basically one API call. The downside is that VB still won't display these correctly if PNG has alphablending, but we can draw them flawlessly to a DC while maintaining transparency within the PNG, if any.

Requirement: Vista or better
API: CreateIconFromResourceEx. Also needed is DrawIconEx to render the PNG to DC

Edited: My comments above are a bit misleading. Only if the PNG contains alphablending will you want to use DrawIconEx to draw the image. Otherwise, just assign the returned stdPicture to any control's Picture property or even the form's Picture property. Also, see post #2 for a possible workaround.

Recommend testing on some large PNGs. I am not sure what the limit of the API may be. I believe Vista topped out around 768x768. However, never really researched it and that may have been a soft-limit. In other words, this may not be a perfect solution for all PNGs. But on Win10, for example, no problem with typical 1024x768 PNGs.

Simply get the PNG data into a zero-bound byte array (from file or via LoadResData) and pass to this function. The function creates a stdPicture object wrapped around an icon created from the PNG. You don't have to worry about destroying the icon since VB will do it when the stdPicture is released or goes out of scope.

Code:

' APIs first

Private Declare Function CreateIconFromResourceEx Lib "user32.dll" (ByRef presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "OleAut32.dll" (lpPictDesc As Any, riid As Any, ByVal fPictureOwnsHandle As Long, ipic As IPicture) As Long
Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long


Public Function LoadPNGtoICO(pngData() As Byte) As IPicture
   
    Dim hIcon As Long
    Dim lpPictDesc(0 To 3) As Long, aGUID(0 To 3) As Long
   
    hIcon = CreateIconFromResourceEx(pngData(0), UBound(pngData) + 1&, 1&, &H30000, 0&, 0&, 0&)
    If hIcon Then
        lpPictDesc(0) = 16&
        lpPictDesc(1) = vbPicTypeIcon
        lpPictDesc(2) = hIcon
        ' IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}
        aGUID(0) = &H7BF80980
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        ' create stdPicture
        If OleCreatePictureIndirect(lpPictDesc(0), aGUID(0), True, LoadPNGtoICO) Then
            DestroyIcon hIcon
        End If
       
    End If
   
End Function

Example. Some error checking provided, tweak to your liking. Replace the bold blue text below with a valid file/path name of a PNG.
Code:

' DrawIconEx API:
Private Declare Function DrawIconEx Lib "user32.dll" (ByVal hDC As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long


Private Sub Command1_Click()
    Dim tPicture As StdPicture
    Dim imgData() As Byte, fnr As Integer, lSize As Long
   
    fnr = FreeFile()
    On Error Resume Next
    Open [the file] For Binary As #fnr
    If Err Then
        MsgBox Err.Description
        Exit Sub
    End If
    On Error GoTo 0
    lSize = LOF(fnr)
    If lSize = 0& Then
        MsgBox "File does not exist", vbExclamation + vbOKOnly
        Close #fnr
        Exit Sub
    End If
    ReDim imgData(0 To lSize - 1&)
    Get #fnr, 1, imgData()
    Close #fnr
   
    Set tPicture = LoadPNGtoICO(imgData())
    Erase imgData()
    If tPicture Is Nothing Then
        MsgBox "Failed to load the file. May not be valid PNG format or pre-Vista operating system.", vbExclamation + vbOKOnly
    Else
        ' change the 3rd & 4th 0& to destination width & height respectively. Zero = actual size
        DrawIconEx Me.hDC, 0&, 0&, tPicture.Handle, 0&, 0&, 0&, 0&, &H3
    End If
   
End Sub


Viewing all articles
Browse latest Browse all 1531

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>