Search code examples
delphiruntimeimagelist

Create and populate an ImageList at runtime


Coming from C# and Visual Studio to Delphi 10.1 Berlin is very hard for me, but some performance is crucial, and I haven't worked with Delphi for a long time (more than 10 years), so I'm blocked.

I need to create an ImageList at run-time and store it in a singleton object, but I can't do that due to an exception while reading memory.

Here is an extract of my code:

ImagesRessource = class
private
  _owner: TComponent;   
  _imageList: TimageList;
  _man24: TPngImage;
  constructor Create;
  function GetBmpOf(png: TPngImage): TBitmap;
public
  procedure  Initialize(own: TComponent);   
end;

implementation

constructor ImagesRessource.Create;
begin
  ;
end;

procedure ImagesRessource.Initialize(owner: TComponent);
var
  bmp: TBitmap;
  RS  : TResourceStream;
begin
  try
    _man24 := TPngImage.Create;
    RS := TResourceStream.Create(hInstance, 'man_24', RT_RCDATA);
    _man24.LoadFromStream(RS);
    bmp := GetBmpOf(_man24);
    _imageList := TimageList.Create(owner);
    _imageList.Width := 24;
    _imageList.Height := 24;
    _imageList.AddMasked(Bmp, Bmp.TransparentColor); // exception read memory here
  except
    raise;
  end;
end;

function ImagesRessource.GetBmpOf(png: TPngImage): TBitmap;
var
  bmp: TBitmap;
begin
  bmp := TBitmap.Create;
  bmp.Width := png.Width;
  bmp.Height := png.Height;
  png.Draw(bmp.Canvas, bmp.Canvas.ClipRect);
end;

What wrong here?


Solution

  • You don't return anything from GetBmpOf. You must assign to the Result variable.)

    function ImagesRessource.GetBmpOf(png: TPngImage): TBitmap;
    begin
      Result := TBitmap.Create;
      Result.Width := png.Width;
      Result.Height := png.Height;
      png.Draw(Result.Canvas, Result.Canvas.ClipRect);
    end;
    

    You also leak the PNG image _man24, which in any case should be a local variable. You hard code the size of 24 in some places but not others. Your try except block is pointless.