A better LoadPicture


You can load any icon into a picture if you have a handle for the icon. The IconToPicture function (PICTOOL.BAS) turns an icon handle into a Picture object in the same way BitmapToPicture turns a bitmap into a picture. (For more information, see “Using Bitmaps,” page 453). Therefore, if you could get the handle of a small icon image out of a multi-image icon file, you could load it into a picture.


It so happens that the Win32 API has a new LoadImage function that delivers icons, cursors, and bitmaps. I don’t need it for bitmaps, and I haven’t figured out a good way to use it for cursors, but it works fine for icons. You tell it what size icon you want, and it gives you a handle to that icon. As an added benefit, LoadImage can load from either an ICO file or from an icon resource. In other words, it does most of the work of the Visual Basic LoadPicture and LoadRes­Picture functions. I use LoadImage to create a better LoadAnyPicture that takes an additional optional argument that specifies what kind of icon to load. Here’s how the Test Icons program calls my new LoadPicture:

‘ Load icon with Basic’s LoadPicture (system metrics size)
Set img(eipBasic).Picture = LoadPicture(“i.ico”)
Set pb(eipBasic).Picture = LoadPicture(“i.ico”)
‘ Load icon with Basic’s LoadPicture (system metrics size)
Set img(eipDefault).Picture = LoadAnyPicture(“i.ico”, eisDefault)
Set pb(eipDefault).Picture = LoadAnyPicture(“i.ico”, eisDefault)
‘ Load icon stretched to system metrics size
Set img(eipShell).Picture = LoadAnyPicture(“i.ico”, eisShell)
Set pb(eipShell).Picture = LoadAnyPicture(“i.ico”, eisShell)
‘ Load first icon image in file with its real size
Set img(eipImage).Picture = LoadAnyPicture(“i.ico”, eisImage)
Set pb(eipImage).Picture = LoadAnyPicture(“i.ico”, eisImage)
‘ Load small (16 by 16) icon, squashing if necessary
Set img(eipSmall).Picture = LoadAnyPicture(“i.ico”, eisSmall)
Set pb(eipSmall).Picture = LoadAnyPicture(“i.ico”, eisSmall)
‘ Load huge (48 by 48) icon
Set img(eipHuge).Picture = LoadAnyPicture(“i.ico”, eisHuge)
Set pb(eipHuge).Picture = LoadAnyPicture(“i.ico”, eisHuge)

Notice the fourth set of commands (the ones with the eisImage parameter). This is how you load small icons and other icons of unusual size from single-image icon files. Normally, Visual Basic stretches these icons to the system metrics size, but if you give the eisImage constant, you should get the real size of the image. In most cases, you should let Windows decide which image to use and when. But if you had an icon editor that let you define icons of any size, you could use LoadAnyPicture with eisImage to get transparent images for animation.


Here’s the code for the better LoadPicture from PICTOOL.BAS:

Function LoadAnyPicture(Optional sPicture As String, _
Optional eis As EIconSize = eisDefault _
) As Picture
Dim hIcon As Long, sExt As String, xy As Long, af As Long
‘ If no picture, return Nothing (clears picture)
If sPicture = sEmpty Then Exit Function
‘ Use default LoadPicture for all except icons with argument
sExt = MUtility.GetFileExt(sPicture)
If UCase$(sExt) <> “.ICO” Or eis = -1 Then
Set LoadAnyPicture = VB.LoadPicture(sPicture)
Exit Function
End If

Select Case eis
Case eisSmall
xy = 16: af = LR_LOADFROMFILE
Case eisHuge
xy = 48: af = LR_LOADFROMFILE
Case eisImage
xy = 0: af = LR_LOADFROMFILE Or LR_LOADREALSIZE
Case eisShell ‘ Get icon size from system
xy = GetShellIconSize(): af = LR_LOADFROMFILE
Case Is > 0 ‘ Use arbitrary specified size—72 by 72 or whatever
xy = eis: af = LR_LOADFROMFILE
Case Else ‘ Includes eisDefault
xy = 0: af = LR_LOADFROMFILE Or LR_DEFAULTSIZE
End Select
hIcon = LoadImage(0&, sPicture, IMAGE_ICON, xy, xy, af)
‘ If this fails, use original load
If hIcon <> hNull Then
Set LoadAnyPicture = IconToPicture(hIcon)
Else
Set LoadAnyPicture = VB.LoadPicture(sPicture)
End If
End Function

This function deals only with icons. The first section of code checks for other types or for a command line without an optional argument, and then calls the normal LoadPicture to do the work. If an optional argument is provided, the code sets up the appropriate size and flags and calls LoadImage. Finally it checks to see whether LoadImage worked, and, if not, it again falls back on the original LoadPicture. The LoadImage function is implemented as a stub under Windows NT 3.51, so you’ll always fall through to the old LoadPicture. That’s OK because all icons are the same size in that environment.