TImageList
│
English (en) │
français (fr) │
русский (ru) │
中文(中国大陆) (zh_CN) │
TImageList is a component that provides a list of images that can be shared between other components like TMainMenu/TMenuItem, TToolBar/TToolButton, TActionList, TBitBtn or TSpeedButton. All images have the same size as specified by the Width and Height property of TImageList. A component needing an image specifies this by means of its ImageIndex property.
Multiple-resolution TImageList in Lazarus 1.9 and newer
In Lazarus 1.9 the TImageList was rewritten to support multiple resolutions of one image.
Every LCL control that supports an ImageList has now a new ImagesWidth property to decide what custom width at 96 PPI (100% scale) is to be used. Example: TToolBar.Images/ImageWidth, TListView.LargeImages/LargeImagesWidth.
Set the Scaled property to True and the image list will automatically pick up the scaled image in your High-DPI aware LCL application (provided that the option "Use LCL Scaling" has been checked in the project options).
Demo applications
There are 2 demo applications in Lazarus sources:
- examples/imagelist_highdpi_designtime
- examples/imagelist_highdpi_runtime
Changes affecting backwards compatibility
Add method
- Old behavior: the image got sliced if too big or extended if too small.
- New behavior: the image is scaled to all resolutions in the image list.
- Reason: Image List now supports multiple resolutions.
- Remedy: use AddSliced (if the image consists of several icons to be added) or AddSlice (if one image from a custom rect has to be added - also rect outside the image is supported).
How to create a multi-resolution ImageList in the application
- In the first step you must tell the Imagelist which image sizes are needed.
- Decide on the basic image size, usually 16x16. This is used at 96ppi screen resolution (in Windows: 100%).
- If your application will also run at 144ppi (150%) or 192ppi (200%), it will also need images at 24x24 and 32x32 (24 = 150% of 16, 32 = 200% of 16).
- In the case that some controls require a larger image size at 96pp, say 32x32, you should also prepare the imagelist for these scaled sizes, i.e. size 48 (=150% of 32) and 64 (=200% of 32) in this example.
- Click on the New resolutions button and specify each of these extra sizes (only the width must be entered). The 16x16 size does not need to be added by the New resolutions button because it is already known from the Imagelist.Width and .Height properties.
- In the next step you add the images themselves.
- Click on the Add more resolutions button.
- Navigate to the folder in which your images are stored (The png image format is highly recommended). Lazarus 2.3+, for example, has the images/general_purpose folder in its installation directory which is full of free png images designed for typical applications (thanks to Roland Hahn...). (svg master files can be found at https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/image_sources/lazarus/images/general_purpose/).
- Multi-select all sizes of the image that you want to load.
- OK loads the images into the image list editor; missing sizes will be scaled down from larger sizes in surprisingly good quality.
- Repeat with the other motives that you need.
- Add only images that you need - they require a fairly large amount of memory.
- If you wonder about the difference between the Add and Add more resolutions buttons: When you click Add only a single image can be selected, and the other sizes are extrapolated from it. Add more resolutions, on the other hand, allows multi-selection so that the individual images of the specific size can be selected.
- The Replace and Replace all resolutions buttons allow to replace the image selected in the imagelist editor by another motif.
- Delete removes all sizes of the image selected in the imagelist.
- Clear erases the entire imagelist.
- If you draw the images yourself, you may skip all the intermediate sizes. The minimum is to draw the largest images that you need; the smaller ones are scaled down automatically upon loading. However, the smallest image (16x16), sometimes also 24x24, appears a bit fuzzy; therefore, it is recommended to provide special versions of these sizes as well. It is maybe a good idea to draw the images in vector format (svg, using Inkscape) and to export to the needed size in png format.
- Finally select the controls which require the non-standard default size and set their ImagesWidth to the corresponding value. In case of a TListView having a SmallImages and a LargeImages property, for example, set the LargeImagesWidth to 32; the SmallImagesWidth can stay at its default value, 0, because it is interpreted as the default size defined by the Imagelist.Width.
- In order to activate automatic scaling of image sizes according to the current resolution of the monitor you must set the Scaled property of the Imagelist to true. Usually you should also provide a handler for the Imagelist event OnGetWidthForPPI to define that images should be scaled also for intermediate resolutions which were not added explictly in the "New resolutions" step above. (Otherwise only the next-smaller predefined image sizes will be used).
procedure TForm1.ImageList1GetWidthForPPI(Sender: TCustomImageList;
AImageWidth, APPI: Integer; var AResultWidth: Integer);
begin
AResultWidth := AImageWidth * APPI div 96;
end;
Redesigned ImageList Component Editor in Lazarus v3.99 and newer
In Lazarus 3.99 the ImageList component editor was redesigned to better take care of translated strings. The button stack in the center was removed and their functionality was moved into a toolbar with dropdown menus for each group of actions:
- Button Add
- Add image(s) with single resolution: opens a file dialog to select one ore more images (CTRL+Click). These image will be added to the imagelist as individual items, and all missing sizes ("resolutions") of each image will be created from each single image.
- Add image with multiple resolutions: opens a file dialog which is configured to allow selection of all images in all sizes ("resolutions") defined in the imagelist. Missing resolutions will be calculated from the existing resolutions.
- Add sliced: When several images have been combined into a large image (e.g. by the "Save All" function) the individual images can be extracted and added by this function.
- Paste image from clipboard: An image contained in the clipboard is added to the imagelist, and the other image sizes are constructed from it.
- Button Replace
- Replace single resolution of an image: opens a file dialog to select an image which will replace the currently loaded image of its size.
- Replace all resolutions of an image: opens a file dialog in which you can select all images at various sizes (CTRL+Click) which will replace all resolutions of the selected image. Missing sizes will be created from the other sizes.
- Button Remove
- Delete image: removes the currently selected image from the imagelist along with all its resolutions
- Clear list: clear the entire image list which is empty afterwards.
- Button Move Up: moves the currently selected image in the imagelist up
- Button Move Down: moves the currently selected image in the imagelist down
- ButtonSave
- Save image: Saves the currently selected image in its base resolution to file.
- Save all: Combines all images of the image list in their base resolution to an image stripe which is saved to file. Such an image stripe can be loaded in another project by the "Add sliced" command.
- Button Resolutions
- Register new resolution (images size): opens an input box in which the user can enter a new image size. This size will be registered in the imagelist. The imagelist will create images of that new resolution from the existing images.
- Delete resolution (image size): opens a dialog from which the user can select an image resolution (image size) which will be deleted from the imagelist.
High-DPI alternative for Lazarus 1.8 and older: resize all images in TImageList
This is useful for example for High DPI scaling to get icons with higher resolution for TActionList, TMainMenu and TToolBar. Note: This may not work correctly with all widgetsets on all platforms. Note also: This code is not required for Laz 1.9+.
procedure ScaleImageList(ImgList: TImageList; NewWidth, NewHeight: Integer);
var
TempImgList: TImageList;
TempBmp1: TBitmap;
TempBmp2: TBitmap;
I: Integer;
begin
TempImgList := TImageList.Create(nil);
TempBmp1 := TBitmap.Create;
TempBmp1.PixelFormat := pf32bit;
TempBmp2 := TBitmap.Create;
TempBmp2.PixelFormat := pf32bit;
TempBmp2.SetSize(NewWidth, NewHeight);
try
TempImgList.Width := NewWidth;
TempImgList.Height := NewHeight;
for I := 0 to ImgList.Count - 1 do begin
// Load image for given index to temporary bitmap
ImgList.GetBitmap(I, TempBmp1);
// Clear transparent image background
TempBmp2.Canvas.Brush.Style := bsSolid;
TempBmp2.Canvas.Brush.Color := TempBmp2.TransparentColor;
TempBmp2.Canvas.FillRect(0, 0, TempBmp2.Width, TempBmp2.Height);
// Stretch image to new size
TempBmp2.Canvas.StretchDraw(Rect(0, 0, TempBmp2.Width, TempBmp2.Height), TempBmp1);
TempImgList.Add(TempBmp2, nil);
end;
ImgList.Assign(TempImgList);
finally
TempImgList.Free;
TempBmp1.Free;
TempBmp2.Free;
end;
end;
Example with ComboBox
To use TImageList, drop an TImageList object onto the form. In this example we need six images.
All images must be the same size. If two sizes of image are to be used, then two TImageLists must be used.
Set the height and width of the images in the Object Inspector; In this case 50px wide by 18px high.
Set Style to csOwnerDrawFixed.
Double-click on the TImageList icon to open the TImageList editor. Make sure that the icons show correctly when selected. If they are smaller than expected, check the size in the Object Inspector <F11>. You may have to reload the images.
Place a ComboBox on the form and name it cbSymbols.
In the FormCreate event enter:
cbSymbols.Items.Clear;
for I := 0 to 5 do
cbSymbols.Items.Add('');
cbSymbols.ItemIndex := 0;
This will write 6 blank entries, and select the first.
In the OnDrawItem event for cbSymbols place the following code:
procedure TMyForm.cbSymbolsDrawItem(
aControl: TWinControl;
iIndex: Integer;
aRect: TRect;
aState: TOwnerDrawState );
var
cnv: TCanvas;
begin
if not (aControl is TComboBox) then exit;
cnv := TComboBox( aControl ).Canvas;
Imagelist1.Draw( cnv, aRect.Left+2, aRect.Top+2, iIndex );
end;
The adjustments (+2) are to center the image in the item, if necessary.
Example with SpeedButton
Add images to the ImageList1 like in the previous example and use:
ImageList1.GetBitmap(iIndex,SpeedButton1.Glyph);
See also