Drawing an ImageList's Images into a StringGrid Column

We started this topic by demonstrating how to put an image into a StringGrid header. The technique used here enables you to draw an image into any cell. Note that you need to supply to the StringGrid's Draw procedure the X and Y values of the top left of the image relative to the top left of the StringGrid. You can either do this calculation yourself (as in the commented out code in procedure StringGrid1DrawCell) or make use of the TRect parameter for the cell as shown. This is a screenshot of the demonstration:
Screenshot of program in action

Screenshot of program in action

  1. If you have not already done so, download the 48x48 flag images for Australia, Austria, Belgium and Botswana by following the links from printableworldflags.com.
  2. Start a new application, select menu item File > Save All, then save the project as ImageListDemo3 and the unit as uImageListDemo3.
  3. Drop a TImageList from the Common Controls component tab onto the form.
  4. Using the Object Inspector, change the values of the Height and Width properties of ImageList1 from 16 to 48.
  5. Right click on ImageList1 in the Object Inspector and select menu item ImageList Editor ...
  6. Click the Add ... button of the ImageList Editor, navigate to where you saved the map icons, and open Argentina.png.
  7. Repeat the last step for Austria.png, Belgium.png, then Botswana.png and click the OK button.
  8. Drop onto the form a TStringGrid from the Additional components tab.
  9. Set the DefaultColWidth to 80 and the DefaultRowHeight to 48.
  10. Paste this code to replace the default code in the unit.
    unit uImageListDemo3;
    {$mode objfpc}{$H+}
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids, ExtCtrls;
      TCountry = record
        Name, Capital: string;
        Population, Area: integer;
      TForm1 = class(TForm)
        ImageList1: TImageList;
        StringGrid1: TStringGrid;
        procedure FormCreate(Sender: TObject);
        procedure StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
                                      aRect: TRect; aState: TGridDrawState);
          Countries: array[0..3] of TCountry =
                     ((Name: 'Australia'; Capital: 'Canberra'; Population: 24000000; Area: 7692024),
                     (Name: 'Austria'; Capital: 'Vienna'; Population: 8200000; Area: 84000),
                     (Name: 'Belgium'; Capital: 'Brussels'; Population: 11000000; Area: 31000),
                     (Name: 'Botswana'; Capital: 'Gaborone'; Population: 2200000; Area: 580000));
          FieldNames: array[0..4] of string =
                      ('Name', 'Area (sq km)', 'Population', 'Capital', 'Flag');
      Form1: TForm1;
    {$R *.lfm}
    procedure TForm1.FormCreate(Sender: TObject);
      RowNum, ColNum: integer;
      for ColNum := 0 to 4 do
        StringGrid1.Cells[ColNum, 0] := FieldNames[ColNum];
      for RowNum := 1 to 4 do
          StringGrid1.Cells[0, RowNum] := Countries[RowNum - 1].Name;
          StringGrid1.Cells[1, RowNum] := IntToStr(Countries[RowNum - 1].Area);
          StringGrid1.Cells[2, RowNum] := intToStr(Countries[RowNum - 1].Population);
          StringGrid1.Cells[3, RowNum] := Countries[RowNum - 1].Capital;
    procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
                                         aRect: TRect; aState: TGridDrawState);
      if (aCol = 4) and (aRow > 0) then
        // ImageList1.Draw(StringGrid1.Canvas, 336, 48 * aRow, aRow - 1);
        ImageList1.Draw(StringGrid1.Canvas, aRect.Left + 16, aRect.Top, aRow - 1);
  11. Using the Object Inspector, select FormCreate for the OnCreate event of the form and StringGrid1DrawCell for the OnDrawCell event of StringGrid1.
  12. Execute the program.
Programming - a skill for life!

Instructions for using an ImageList with a ComboboxEx and a StringGrid in Lazarus