delphi и отображение элементов списка

Я использую список для отображения простого списка имен файлов. У меня также есть компонент редактирования, который позволяет мне искать эти элементы с помощью простого:

procedure TForm1.Edit1Change(Sender: TObject);
const
  indexStart = -1;
var
  search : array[0..256] of Char;
begin
  if edit1.Text='' then exit;
  StrPCopy(search, Edit1.Text) ;
  ListBox1.ItemIndex := ListBox1.Perform(LB_SELECTSTRING, indexStart, LongInt(@search));
end;

Теперь, есть ли способ «выборочно» отображать элементы в списке? Я имею в виду, что если я ищу элемент, начинающийся с «привет», то будут отображаться ТОЛЬКО те, которые приветствуют, либо затемняя те, которые не приветствуются, либо делая видимыми := false вообще. Есть ли способ выполнить это с помощью списка?

Благодарность!

О, это Делфи 7...


person Uri    schedule 13.07.2010    source источник


Ответы (2)


Я всегда делаю так (и делаю это довольно часто):

У меня есть array of string или TStringList, содержащие элементы списка. Затем в Edit1Change я очищаю свойство Items и добавляю только те строки, которые соответствуют тексту в поле редактирования.

Массив строк

Если вы работаете с массивом строк, например

var
  arr: array of string;

который как-то инициализируется, как в

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetLength(arr, 3);
  arr[0] := 'cat';
  arr[1] := 'dog';
  arr[2] := 'horse';
end;

тогда вы можете сделать

procedure TForm1.Edit1Change(Sender: TObject);
var
  i: Integer;
begin
  ListBox1.Items.BeginUpdate;
  ListBox1.Items.Clear;
  if length(Edit1.Text) = 0 then
    for i := 0 to high(arr) do
      ListBox1.Items.Add(arr[i])
  else
    for i := 0 to high(arr) do
      if Pos(Edit1.Text, arr[i]) > 0 then
        ListBox1.Items.Add(arr[i]);
  ListBox1.Items.EndUpdate;
end;

Это отобразит только те строки в массиве, которые содержат Edit1.Text; строка не должна начинаться с Edit1.Text. Для этого замените

Pos(Edit1.Text, arr[i]) > 0

с участием

Pos(Edit1.Text, arr[i]) = 1

TStringList

В случае TStringList, как в

var
  arr: TStringList;

и

procedure TForm1.FormCreate(Sender: TObject);
begin
  arr := TStringList.Create;
  arr.Add('cat');
  arr.Add('dog');
  arr.Add('horse');
end;

ты можешь сделать

procedure TForm1.Edit1Change(Sender: TObject);
var
  i: Integer;
begin
  ListBox1.Items.BeginUpdate;
  ListBox1.Items.Clear;
  if length(Edit1.Text) = 0 then
    ListBox1.Items.AddStrings(arr)
  else
    for i := 0 to arr.Count - 1 do
      if Pos(Edit1.Text, arr[i]) = 1 then
        ListBox1.Items.Add(arr[i]);
  ListBox1.Items.EndUpdate;
end;

Чувствительность к регистру

В приведенном выше коде используется сопоставление с учетом регистра, поэтому, например, «bo» не будет соответствовать «Boston». Чтобы сделать код нечувствительным к регистру, напишите

if Pos(AnsiLowerCase(Edit1.Text), AnsiLowerCase(arr[i])) > 0 then

вместо

if Pos(Edit1.Text, arr[i]) > 0 then
person Andreas Rejbrand    schedule 13.07.2010
comment
это может сработать. проблема, которую я вижу, заключается в том, что я не знаю, сколько элементов в списке. это не исправлено. будет сложно установить размер массива с помощью SetLength. если только... я могу использовать SetLength позже, чтобы сбросить длину массива? или лучше использовать TStringList? - person Uri; 13.07.2010
comment
Большинство людей всегда работают с TStringList, но лично я хочу делать все вручную, поэтому я всегда работаю с array of string. Вы можете изменить длину динамического массива в любое время с помощью SetLength. Если вы увеличите длину, старые элементы останутся. - person Andreas Rejbrand; 13.07.2010
comment
Хм. я пытаюсь с tliststring. Когда я попытался выполнить поиск, ВСЕ элементы исчезли. О, мой плохой, я загружал это неправильно... однако это не работает. У меня есть 2 файла с именами: книга 1 и книга 2. когда я ищу книгу, она находит бо файла с именем места в бостоне, но это все - person Uri; 14.07.2010
comment
понял, я просто добавил нижний регистр () к Pos (нижний регистр (Edit1.Text), нижний регистр (arr [i])), чтобы сделать его нечувствительным к регистру. Благодарность! - person Uri; 14.07.2010
comment
@Uri: Да, я думал, что проблема в этом, поэтому я даже обновил свой ответ! - person Andreas Rejbrand; 14.07.2010

То, что вы просите, может быть реализовано путем подключения стандартного Win32 API IAutoComplete подключается к стандартному TEdit, TListBox не требуется. Не так уж сложно подключить объект TStrings к IAutoComplete, чтобы он знал, какие строки доступны для поиска.

person Remy Lebeau    schedule 14.07.2010