Delphi. Панель Additional. Компонент CheckListBox. Часть 2.

Продолжим рассмотрение свойств компонента CheckListBox.

Свойство Style

Это свойство аналогично свойству «Style» в компоненте «ListBox». Свойство «Style» может принимать пять различных значений. Три из них мы уже рассмотрели: «lbStandard», «lbOwnerDrawFixed» и «lbOwnerDrawVariable».

В большинстве случаев вполне подходит первое значение «lbStandard». При этом значении управление чекбоксами компонента происходит автоматически при клике по чекбоксу.

Если для большей информативности в каждую строку надо добавить изображения, причем размеры всех изображений одинаковы и не больше значения «ItemHeight», то необходимо использовать стиль «lbOwnerDrawFixed».

Если же в разных строках требуется размещать изображения разной высоты, или использовать шрифты разного размера, то необходимо использовать стиль lbOwnerDrawVariable».

При работе с «CheckListBox» (так же, как и с «ListBox»), вознпикает одна неприятная ситуация. При небольшом количестве строк их можно ввести непосредственно на этапе редактирования, используя свойство «Items».

Но уже несколько десятков строк вводить становится затруднительно. Поэтому значения строк подготавливают в каком-либо текстовом редакторе, а затем загружают их программно с помошью процедуры:

CheckListBox1.Items.LoadFromFile(«имя_файла»);

Если количество строк переваливает за сто тысяч, то время загрузки ощутимо увеличивается до секунд, а то и десятков секунд. Кроме того, это заметно в случае добавления/удаления строк, организации поиска и в других случаях.

Если же значение свойства «style» назначить «lbVirtual», то загрузка будет происходить почти мгновенно. Происходит это потому, что значения не загружаются в сам компонент (то есть не хранятся в сегменте программы), а берутся из кучи по мере надобности небольшими порциями, чтобы отобразить их в окне компонента.

Это наглядно видно в следующем видео, где 130000 записей загружается в левый «CheckListBox» стандартном режиме «lbStandard»и в правый «CheckListBox» режиме «lbVirtual».

Однако в реализации стиля «lbVirtual» есть свои особенности. Загрузить значения обычным образом нельзя. Например, если написать:

procedure TForm1.BitBtn1Click(Sender: Tobject);
begin
CheckListBox2.Count:=130000;
CheckListBox2.Items.LoadFromFile(‘9-1 — 129278.txt’);
end;

и затем щелкнуть по кнопке, то мы увидим следующую картину:

То есть текстовые значения не загружаются и чекбоксы на клики не реагируют . Так или иначе, попробуем обойти эту особенность и заставить компонент правильно функционировать.

Предварительные замечания.

Предварительно необходимо провести ряд подготовительных операций:

1) Подготовим две картинки в *.bmp формате:

2) Поместим их в компонент «ImageList».

3) Для чтения данных из файла и их сохранения, используем невизуальный компонент «TstringList».

4) Организуем отображение чекбоксов и строковых данных в обработчике события «onDrawItem», которому соответствует метод «CheckListBox1DrawItem».

5) Реакцию на щелчок по чекбоксу организуем в методе «CheckListBox1ClickCheck», соответствующему обработчику события «onClickCheck».

Дополнительно нам понадобится:
type trec=record b:boolean; t:string; end;
var ar1:array of trec;
SL:TStringList;
m:integer=0;

Поле «b» записи «trec» будет хранить состояние флажка: «true» — установлен, «false» — не установлен.

Поле «t» хранит текст строки.

Программный код

type
trec=record b:boolean; t:string; end;

var
Form1: Tform1;
SL:TStringList;
ar1:array of trec;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: Tobject);
var i,ii:integer;
begin
SL:= TstringList.Create; //создаём невизуальный компонент «StringList»
SL.LoadFromFile(‘9-1 — 129278.txt’);//загружаем в «SL» данные из файла (файл предварительно должен быть разбит на строки)
i:=SL.Count;//Определить количество строк в «SL»
SetLength(ar1,i);//устанавливаем размерность динамического массива
CheckListBox1.Count:=i;//это абсолютно необходимая команда в виртуальном режиме! Без неё загрузится ноль строк.

for ii:=0 to i-1 do//заполняем массив значениями
begin
ar1[ii].t:=SL.Strings[ii];
ar1[ii].b:=false;
end;

end;

procedure TForm1.CheckListBox1ClickCheck(Sender: Tobject);
var i,h,top,bottom:integer; r:trect;
begin
i:=CheckListBox1.ItemIndex;//определяем номер строки, в которой находится чекбокс, по которому произведён щелчок
//условие «if» будет работать как переключатель. При каждом щелчке значение поля «b» будет меняться на противоположенное.
if ar1[i].b=false then ar1[i].b:= true
else ar1[i].b:=false;

//чтобы произвести перерисовку строк в компоненте «CheckListBox», необходимо, чтобы произошло событие «onDrawItem». Оно может произойти при изменении внешнего вида компонента (например, если перекрыть хотя бы часть изображения «CheckListBox» другим окном, или принудительно что-либо нарисовать на канве компонента. Так как ничего подобного мы не производим, то вызываем перерисовку компонента принудительно, с помощью процедуры:
CheckListBox1.Repaint;
end;

procedure TForm1.CheckListBox1DrawItem(Control: TWinControl;
Index: Integer; Rect: TRect; State: TownerDrawState);
begin
//отрисовываем чекбокс
if not (ar1[Index].b) then
ImageList1.Draw(CheckListBox1.Canvas,2,Rect.Top,0)
else
ImageList1.Draw(CheckListBox1.Canvas,2,Rect.Top,1);

CheckListBox1.Canvas.FillRect(Rect); //эту строку надо добавлять обязательно. Она формирует фон строки, закрашивая прямоугольник «Rect» текущей строки текущим цветом кисти
//выводим в текущую строку (с индексом «Index») текст
CheckListBox1.Canvas.TextOut(20,Rect.Top+1,inttostr(Index)+’ ‘+ar1[Index].t);
end;

procedure TForm1.FormDestroy(Sender: Tobject);
begin
SL.Destroy;//невизуальный компонент не имеет «Owner» (хозяина), поэтому он не будет автоматически уничтожен в момент закрытия программы. Поэтому проводим уничтожение компонента «вручную». («FormDestroy» срабатывает, когда программа удаляется из памяти)
end;

Это соответствует следующему интерфейсу программы:

Таким образом, в виртуальном режиме компонент является средством отображения информации, которая хранится отдельно от него в динамической памяти.

Посмотрим результат работы программы:

Свойство IntegralHeight

Это свойство определяет, отображаются ли в списке элементы, только частично входящие по высоте. Если «IntegralHeight=false», то высоту окна списка можно установить на любое значение, но последний элемент при этом может отображаться не полностью. Например:

Свойство «IntegralHeight» управляет высотой самого списка. Если «IntegralHeight=true» и свойство «Style» имеет значение «lbStandard», или «lsOwnerDrawFixed», то высота окна списка всегда будет кратна значению свойства «IntegralHeight» и строки по высоте всегда будут отображаться полностью:

Если значение свойства «Style»установлено в «lbOwnerDrawVariable», то установка свойства «IntegralHeight» в «true» не будет иметь никакого эффекта.

Свойство MultiSelect

Свойство «MultiSelect» можно установить только программно. Если

CheckListBox2.MultiSelect:=true; то возможен множественный выбор строк при одновременном нажатии клавиши «Ctrl» (множественный выбор в разбивку), или «Shift» (сплошной множественный выбор) и кликам мышью по разным строкам. Например,

Рассмотрим пример. По умолчанию значение «MultiSelect» равно «false». Следующий код работает как переключатель, последовательно меняя состояние «MultiSelect» и надпись на кнопке:

procedure TForm1.Button4Click(Sender: Tobject);
begin
if not CheckListBox1.MultiSelect then
begin
Button4.Caption:=’MultiSelect=true’;
CheckListBox1.MultiSelect:=true
end
else
begin
button4.Caption:=’MultiSelect=false’;
CheckListBox1.MultiSelect:=false;
end;
end;

Нажатие следующей кнопки считывает выделенные строки и размещает их в компоненте «Memo»:

procedure TForm1.Button5Click(Sender: Tobject);
var n,index:integer;
begin
n:=Length(ar1)-1;
for index:=0 to n do
begin
if CheckListBox1.Selected[index] then
Memo1.Lines.Append(ar1[Index].t);
end;
end;

Функция «Length» определяет длину массива (или отдельной ветки массива), а также длину строки.

Свойство «Selected» содержит массив булевых значений, соотнесённых со строками. Значение по умолчани равно «false». Для выделенных строк значение меняется на «true».

Результат работы кода:

Свойство Sorted

Если выставить это свойство в «true», то строки в списке отсортируются по алфавиту.

Ссылка на CheckListBox. Часть 1.

***

Обновлено: 29.08.2021 — 13:14

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *