Jump to content

Keeping ImageList in sync as ListView changes


DrJohn
 Share

Recommended Posts

Hello all.  It's me again.

I've got a ListView with an associated ImageList to display icons.  What I seem to be hung up on is how to keep the ImageList updated to match the ListView as the latter changes.  I thought it was the case that the indices of the items in the ListView and those in the ImageList just needed to match.  So, for example, if I:

  • Delete an item from the ListView [_GUICtrlListView_DeleteItem()], and also delete the image at the matching index in the ImageList [_GUIImageList_Remove()].
  • Then add a new item to the end of the ListView [_GUICtrlListView_AddItem()], and correspondingly add an image at the end of the ImageList [_GUIImageList_AddIcon()]

Shouldn't everything stay in sync?

Here's the code I thought would work:

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <FontConstants.au3>
#include <WindowsConstants.au3>
#include <GuiImageList.au3>

Test()

func Test()

    $gui = GUICreate("Test", 400, 300)

    ; Create ListView
    $lv = _GUICtrlListView_Create($gui, "", 10, 10, 380, 240, $LVS_DEFAULT)
    _GUICtrlListView_AddColumn($lv, "Col1", 50)
    _GUICtrlListView_AddColumn($lv, "Col2", 50)
    for $i = 0 to 2
        $s = StringFormat("%d,1", $i+1)
        _GUICtrlListView_AddItem($lv, $s, $i)
        $s = StringFormat("%d,2", $i+1)
        _GUICtrlListView_AddSubItem($lv, $i, $s, 1)
    next

    ; Add ImageList
    $img_list = _GUIImageList_Create(16, 16, 5, 3)
    for $i = 0 to 2
        $ico = StringFormat("%d.ico", $i+1)
        _GUIImageList_AddIcon($img_list, $ico)
    next
    _GUICtrlListView_SetImageList($lv, $img_list, 1)

    ;
    $btn = GUICtrlCreateButton("Test", 10, 260, 60, 30)
    GUISetState(@SW_SHOW)
    HotKeySet("^q", Quit)

    ; Loop until the user exits.
    while True
        switch GUIGetMsg()
            case $GUI_EVENT_CLOSE
                Exit

            case $btn
                ; Remove 2nd list item and image
                _GUICtrlListView_DeleteItem($lv, 1)
                _GUIImageList_Remove($img_list, 1)

                ; Add new item to end of ListView
                $idx = _GUICtrlListView_AddItem($lv, "foo")
                _GUICtrlListView_AddSubItem($lv, $idx, "bar", 1)

                ; Add new image to end of ImageList
                _GUIImageList_AddIcon($img_list, "5.ico")
        endswitch
    wend
    GUIDelete()

endfunc

func Quit()
    Exit
endfunc

What seems to happen is that when the new item is added to the ListView, its icon is 1.ico (the first item in the ImageList), rather than 5.ico (the newly added item that should be at the end of the ImageList).

Or do I need to re-create the whole ImageList any time the ListView changes?

A zip file is attached that contains the script and also the .ico files, for easier testing.

Thanks!

/John

test.zip

Link to comment
Share on other sites

Hi

Quote

Shouldn't everything stay in sync?

 

The icons  are assigned to a Specific item in the Listview.

Item #1 will have the icon #1

Item #2 will have the icon #2

Item #3 will have the icon #3

 

When you delete the item #2 the #3 will fall down to the second place, but with the icon still as #3.

When you add an item, it will have the 1st icon assigned to it, as long as you do not specify something else.

therefore after clicking the button, the above picture will look like this:

 

Item #1 will have the icon #1

Item #2 will have the icon #3

Item #3 will have the icon #1

 

You do not need to delete the icons, if you want to reuse them.

If you change your script like this  

 

; Remove 2nd list item and image

                _GUICtrlListView_DeleteItem($lv, 1)

                ; Add new item to end of ListView
                $idx = _GUICtrlListView_AddItem($lv, "foo",_GUICtrlListView_GetItemCount($lv))
                _GUICtrlListView_AddSubItem($lv, $idx, "bar", 1)

                ; Add new image to end of ImageList
                ;_GUIImageList_AddIcon($img_list, "5.ico")

the last added item will get the highest icon number.

 

But, if, with synced, you mean that the item numbers should have their corresponding icon numbers after the delete button was pressed - no, you have to manually adjust them.

If you want to add a new icon, and assign it to the last added item, then you can do following:

case $btn
                ; Remove 2nd list item and image

                _GUICtrlListView_DeleteItem($lv, 1)

                ; Add new image to end of ImageList
                _GUIImageList_AddIcon($img_list, "5.ico")
                ; Add new item to end of ListView
                $idx = _GUICtrlListView_AddItem($lv, "foo", _GUIImageList_GetImageCount($img_list)-1)
                _GUICtrlListView_AddSubItem($lv, $idx, "bar", 1)

But, the more you delete, the more duplicate of the "5.ico" you will have in the ImageLlist !

Quote

Or do I need to re-create the whole ImageList any time the ListView changes?

The best way would be to preload icons (1-5) into the ImageList, and to add them to the Listview items, as needed.

 

Edited by Dan_555

Some of my script sourcecode

Link to comment
Share on other sites

Argh!  I was a complete bonehead!

I somehow never noticed that third parameter to _GUICtrlListView_AddItem() [0-based index of the item's icon in the control's image list].  How I managed not to see that, I can't imagine.

I thought the assignment of an image to an item in the ListView was purely positional (the first item in the ListView gets the first image in the ImageList, the second item in the ListView gets the second item in the ImageList, and so on ...)

There are none so blind as those who will not see.  😬

This pretty well explains it.  Thanks @Dan_555!

/John

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...