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:
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 ImageList has now a new [Images]Width 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.
There are 2 demo applications in Lazarus sources:
Changes affecting backwards compatibility
- 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 multi-resolution ImageList in the application
Advice from forum member wp:
In the first step you must tell the Imagelist which image sizes are needed. Decide on the basic image size, as I said: usally 16x16. This is used at 96ppi screen resolution (in Windows: 100%). If your application will also run at 144ppi (150%) or 192ppi (200%), add the "resolutions" "24" (=150% of the basic size, 16) and "32" (200% of 16) by means of the "New resolutions" buttons in the ImageList editor. If the basic size will be larger, say 32x32, for some controls (e.g. TListView.LargeImages vs. .SmallImages), you should also specify "resolutions" "48" and "64". So, in total, a standard application will require you to add 24 and 32 with the "New resolutions button"; for an application needing also 32x32 images, you have to add 24, 32, 48, and 64 in total. 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 specification.
In the next step you add the images themselves. Click on "Add more resolutions" button. Navigate to the images/general_purpose folder of the Lazarus installation. Click on the 16px version of the image that you want to add. Then Shift-click on the last size of that image to be added. "Open" adds the selected sizes of the image to the image list. Repeat will all other images. Add only images that you need - they require a fairly large amount of memory.
If you do not use the general_purpose images folder and draw the images by yourself, you may skip all the intermediate sizes. The minimum is to draw the larges images that you need; the intermediated smaller sizes are calculated with sufficient quality. However, the smallest image (16x16), sometimes also the 24x24 image, appears a bit fuzzy; therefore, it is recommended to provide special version of these sizes, too.
Finally select the controls which require the 32x32 default size and set their ImagesWidth to 32 so that the 32x32 version of the images is selected at 96ppi.
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;