LISTBOX are very handy to store and retrieve data, that you want to share among all your code. You can use them as you would do for GLOBAL ARRAY or just GLOBAL VARIABLES, without the drawback of native GLOBALS.
One nice thing about LISTBOX is the use of LB_SETITEMDATA or LB_GETITEMDATA, that would let you set a 32-bit value associated with the specified item in a list box, you can use it for example to store properties, or handles, or codeptr, or anything that could fit within a 32-bit LONG/DWORD.
In the Skin Engine project (cf. the SDK section) I am using a similar technic in zAddResource and zDeleteResource to manage the bitmap being used with the custom controls.
In zAddResource, I make sure before creating a new memory bitmap, that I haven't use already the same file name to create a GDIPLUS memory image, in case there is one already, i just reuse it, thus saving memory!
For example using 1 or 100 or 1000 crystal buttons won't change anything, there is just one single image bitmap being used!
Note the way the LISTBOX are created:
CreateWindowEx(0, "LISTBOX", "", %WS_CHILD, 0, 0, 0, 0, hMain, %ID_LISTFNAME, zInstance(), BYVAL %NULL)
We don't need any size nor visibility because we will never show them, the only other style we could use is LBS_SORT in case we need to sort the data to read them in sequence (no more need for ARRAY SORT).
zAddRessource uses TWO // DUAL LISBOX:
one to find the bitmap matching a specific file name, the other to get the filename matching a specific handle.
FUNCTION zAddResource(BYVAL sResource AS STRING) AS LONG
LOCAL hMain, hLISTFNAME, hLISTIMAGE, nIndex, hImage, nCount AS LONG
LOCAL zTmp AS ASCIIZ * 265 ' %MAX_PATH + 5
LOCAL zData AS ASCIIZ * 16
CALL GetShortPathName((sResource), zTmp, SIZEOF(zTmp))
zTmp = UCASE$(zTmp)
hMain = zMainWindow(0)
hLISTFNAME = zGetMainItem(%ID_LISTFNAME)
IF NOT IsWindow(hLISTFNAME) THEN
hLISTFNAME = CreateWindowEx(0, "LISTBOX", "", %WS_CHILD, 0, 0, 0, 0, hMain, %ID_LISTFNAME, zInstance(), BYVAL %NULL)
hLISTIMAGE = CreateWindowEx(0, "LISTBOX", "", %WS_CHILD, 0, 0, 0, 0, hMain, %ID_LISTIMAGE, zInstance(), BYVAL %NULL)
END IF
IF hLISTFNAME THEN
nIndex = SendMessage(hLISTFNAME, %LB_FINDSTRING, -1, VARPTR(zTmp))
IF nIndex > -1 THEN '// We found same resource
CALL SendMessage(hLISTIMAGE, %LB_GETTEXT, nIndex, VARPTR(zData))
hImage = VAL(zData)
' // Get full string item
CALL SendMessage(hLISTFNAME, %LB_GETTEXT, nIndex, VARPTR(zTmp))
' // Delete item before update
CALL SendMessage(hLISTFNAME, %LB_DELETESTRING, nIndex, 0)
CALL SendMessage(hLISTIMAGE, %LB_DELETESTRING, nIndex, 0)
sResource = LEFT$(zTmp, LEN(zTmp) - 4)
nCount = VAL(RIGHT$(zTmp, 4)) + 1
zTmp = sResource + RIGHT$("0000" + LTRIM$(STR$(nCount)), 4)
IF SendMessage(hLISTFNAME, %LB_ADDSTRING, 0, VARPTR(zTmp)) < 0 THEN hImage = 0
IF SendMessage(hLISTIMAGE, %LB_ADDSTRING, 0, VARPTR(zData)) < 0 THEN hImage = 0
ELSE '// Resource doesn't exist, add it
hImage = zCreateImageFromFile((sResource))
IF hImage THEN
zTmp = zTmp + "0001"
IF SendMessage(hLISTFNAME, %LB_ADDSTRING, 0, VARPTR(zTmp)) < 0 THEN CALL zDisposeImage(hImage)
IF hImage THEN
zData = STR$(hImage)
IF SendMessage(hLISTIMAGE, %LB_ADDSTRING, 0, VARPTR(zData)) < 0 THEN hImage = 0
END IF
END IF
END IF
END IF
FUNCTION = hImage
END FUNCTION
SUB zDeleteResource(BYREF hImage AS LONG)
LOCAL nIndex, nCount, hLISTIMAGE, hLISTFNAME AS LONG, sResource AS STRING
LOCAL zData AS ASCIIZ * 16, zTmp AS ASCIIZ * 265
IF hImage THEN
zData = STR$(hImage)
hLISTIMAGE = zGetMainItem(%ID_LISTIMAGE)
IF hLISTIMAGE THEN
nIndex = SendMessage(hLISTIMAGE, %LB_FINDSTRING, -1, VARPTR(zData))
IF nIndex > -1 THEN
hLISTFNAME = zGetMainItem(%ID_LISTFNAME)
IF hLISTFNAME THEN
CALL SendMessage(hLISTFNAME, %LB_GETTEXT, nIndex, VARPTR(zTmp))
' // Delete item before update
CALL SendMessage(hLISTFNAME, %LB_DELETESTRING, nIndex, 0)
CALL SendMessage(hLISTIMAGE, %LB_DELETESTRING, nIndex, 0)
sResource = LEFT$(zTmp, LEN(zTmp) - 4)
nCount = VAL(RIGHT$(zTmp, 4)) - 1
IF nCount > 0 THEN
zTmp = sResource + RIGHT$("0000" + LTRIM$(STR$(nCount)), 4)
CALL SendMessage(hLISTFNAME, %LB_ADDSTRING, 0, VARPTR(zTmp))
CALL SendMessage(hLISTIMAGE, %LB_ADDSTRING, 0, VARPTR(zData))
ELSE '// No more in use, then safely delete the GDIPLUS image
CALL zDisposeImage(hImage)
END IF
END IF
END IF
END IF
END IF
END SUB