Автодополнение в TListBox с использованием данных из ListBox2: пошаговое руководство
Вопрос пользователя заключается в возможности использования системы автодополнения в TListBox, но с данными, взятыми из другого ListBox. Предположим, что у нас есть ListBox1, который должен предлагать автодополнение по мере ввода пользователем символов, и данные для этого должны браться из ListBox2, причем количество элементов в обоих списках одинаковое.
Альтернативный ответ: использование виртуального стиля TListBox
Если установить свойство TListBox.Style в режим lbVirtual или lbVirtualOwnerDraw, то можно использовать событие TListBox.OnData для предоставления строк списку. Автодополнение будет работать, вызывая событие TListBox.OnDataFind, которое позволит найти введенные символы в источнике, который вы определяете. В обработчике этого события можно искать необходимые данные в ListBox2. Важно помнить, что индекс, возвращаемый обработчиком OnDataFind, должен относиться к ListBox1, а не к ListBox2.
Подтвержденный ответ: реализация автодополнения с нуля
Пользователь попытался использовать встроенные возможности, но пришел к выводу, что сочетание различных функций (например, переменной высоты элементов и обработки событий DataFind) невозможно. В результате было принято решение реализовать автодополнение самостоятельно.
Вот примерный код, который может использоваться для реализации автодополнения:
// ...
const
acceptCharz=[' '..'z'];
// ...
type
twoWords=packed record a,b:word; end;
// ...
var
alphs:array[' '..'z'] of twoWords; // индексы первых букв
fs:tStringList; // список для поиска
fnd:string; // буфер для поисковой строки
tk:cardinal; // счетчик тактов для тайминга
// ...
procedure TForm1.Button1Click(Sender: TObject); // процедура, где список заполняется элементами
begin
// ...
if(fs <> nil) then fs.Free;
fs := tStringList.Create;
// fltr - это tListBox, данные которого должны быть источником автодополнения (ListBox2)
fs.AddStrings(fltr.Items);
// ...
end;
procedure TForm1.flKeyPress(Sender: TObject; var Key: Char);
begin
// ...
if(getTickCount - tk >= 800) then fnd := ''; // таймаут автодополнения
tk := getTickCount;
h := CharLowerr(Key); // приведение к нижнему регистру для нечувствительности к регистру
// ...
if(fnd = '') then exit; // если нет строки для поиска
// ...
// fl - это tListBox с кастомным рисованием и стилем OwnerDrawVariable (ListBox1)
// также fl имеет такое же количество элементов, как и fltr
// ...
end;
// ...
Этот код является неким "боilerplate", но он работает. Он позволяет видеть, как выделение перемещается по элементам при вводе символов, и работает практически мгновенно.
Однако, в конечном итоге, было осознано, что лучшим решением в данном случае будет включение свойства автодополнения в ListBox1 и заполнение его данными из ListBox2, а отображение строк можно реализовать через процедуру DrawItem. Также возможно удаление ListBox2 и хранение строк для отображения внутри переменной tStringList. Основной вывод: не спешите писать "боilerplate" и попытайтесь больше думать перед действием.
Этот код можно использовать в качестве основы для реализации собственной функции автодополнения, если это необходимо.
Пользователь спрашивает о реализации автодополнения в `TListBox` с использованием данных из `ListBox2`, рассматривая как использование виртуального стиля, так и создание автодополнения с нуля, с учетом нечувствительности к рег
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.