Постановка задачи. Цель приложения – научиться помещать текст и изображения в список TListBox. Результат работы приложения показан на рис. 38.
Рис. 38. Изображения в списке TListBox
Реализация. Выберем три небольшие картинки и поместим их в папку проекта. На форму положим список TListBox. Установим свойство Style компонента TListBox равным lbOwnerDrawVariable. Опишем глобальные переменные:
const n=3;
fn:array[0..n-1] of string=('Гепард.bmp','Кабан.bmp','Бурундук.bmp');
// Изображения в файлах
// Текст, который поместим в список, в массиве mas
mas:array[0..n-1] of string=('Гепард', 'Кабан', 'Бурундук');
Текст поместим в строки ListBox1.Items с помощью метода Add. Создадим объекты Objects для Items как растровые рисунки класса TBitMap и с помощью метода LoadFromFile загрузим в них изображения. Все это сделаем при наполнении формы.
procedure TForm1.FormCreate(Sender: TObject);
var k:integer;
begin
k:=0;
while k<n do
begin
ListBox1.Items.Add(mas [k]);
ListBox1.Items.Objects[k]:=TBitMap.Create;
(ListBox1.Items.Objects[k] as TBitMap).LoadFromFile(fn[k]);
k:=k+1;
end;
end;
Для компонента TListBox определены два события, связанные с программной прорисовкой элементов списка: OnDrawItem и OnMeasureItem. Обработчик события OnDrawItem получает ссылку на список выбора Control, индекс изображаемого элемента Index, границы элемента Rect.
Прорисовка ведется с помощью свойства Canvas. Свойство Canvas имеется также у формы, поэтому нужно явно указать канву, предварительно преобразовав тип TWinControl в тип TListBox.
var ras:integer; // Расстояние от растра до текста
bt: TBitMap;
begin
(Control as TListBox).Canvas.FillRect(Rect);
// Очищаем прямоугольник
bt:=TBitMap((Control as TListBox).Items.Objects[index]);
if bt<>nil then
begin
bt.Width:=100;
// Вычерчиваем растр
(Control as ListBox).Canvas.BrushCopy(Bounds(Rect.Left+2, Rect.Top, bt.Width, bt.Height), bt, Bounds(0,0,bt.Width, bt.Height), clRed);
ras:=bt.Width + 6;
end
else
ras:=2;
// Выводим текст
(Control as TListBox).Canvas.TextOut(Rect.Left + ras, Rect.Top, (Control as TListBox).Items[Index]);
end;
Событие OnMeasureItem возникает только для Style = lbOwnerDrawVariable. В ходе его обработки программа должна установить нужную высоту очередного элемента. Обработчику передается индекс элемента Index и переменная Height, в которой он должен вернуть высоту элемента. Например:
procedure TForm1.ListBox1MeasureItem(Control: TWinControl; Index: Integer; var Height: Integer);
var bt: TBitMap;
begin
bt:=TBitMap((Control as TListBox).Items.Objects[index]);
if bt<>nil then
Height:=bt.Height +30
else
Height:=35; //abs(ListBox1.Font.Height);
end;
Задание. Реализуйте этот проект как заготовку для проекта «Зоомагазин». Нарисуйте животных и рыб, продаваемых в зоомагазинах, и подпишите, как они называются.