Author Topic: Use LISTBOX to store/retrieve data of any type  (Read 5628 times)

0 Members and 1 Guest are viewing this topic.

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2401
  • Gender: Male
    • www.zapsolution.com
Use LISTBOX to store/retrieve data of any type
« on: August 25, 2007, 06:41:15 PM »
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.
Code: [Select]
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

Code: [Select]
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
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com