c++buildervclc++builder-12-athens

How to replace an image in a TImageCollection?


I'm using a TVirtualImage in a TControlList connected to a TImageCollection. I would like to be able to load an image from a TOpenPictureDialog and replace an image in the Collection. For example, replace the image at index 2 with the image from the dialog box.

I would like something like:

ImageCollection1->Images[2]->Replace(OpenPictureDialog1->FileName);

There is a Name also Logo_HD1.


Solution

  • First, you can't index the TImageCollection::Images property the way you are doing, as it is not an array property. The only reason that Images[2] even compiles is because Images is a pointer, so you are performing pointer arithmetic, but you will not be accessing the array memory correctly. You need to instead use the Images->Items sub-property, which is an indexable array property.

    Second, there is no Replace() method on TImageCollectionItem. You need to instead use its SourceImages property. Which itself is another collection of items 1, where each TImageCollectionSourceItem has an Image property of type TWICImage that holds the actual image data. You can load an image file into a TWICImage object via its LoadFromFile() method.

    With that said, try this instead:

    ImageCollection1->Images->Items[2]->SourceImages->Items[0]->Image->LoadFromFile(OpenPictureDialog1->FileName);
    

    Since you know the name of the TImageCollectionItem that you want to update, you can use the TImageCollection::GetIndexByName() method to get its index within the Images collection, eg:

    int index = ImageCollection1->GetIndexByName(_D("Logo_HD1"));
    ImageCollection1->Images->Items[index]->SourceImages->Items[0]->Image->LoadFromFile(OpenPictureDialog1->FileName);
    

    Lastly, after you have updated the TImageCollection, you need to Invalidate() any UI control that is displaying the Image you have updated so it will repaint itself with the new image data, eg:

    VirtualImage1->Invalidate();
    

    Or, in your example, you'll have to repaint the whole TControlList since you can't access individual items:

    ControlList1->Invalidate();