tags:

views:

80

answers:

2

I'm using a listbox to display a simple list of filenames. I also have an edit component that allows me to search those items via a simple:

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;

Now, is there a way to "selectively" display items on a listbox? What I mean is that If I search for the an item that starts with "hello" then ONLY those that will hello will be displayed, either dimming those than don't or making visible := false altogether. Is there a way to perform this with a listbox?

thanks!

Oh, it's Delphi 7...

+3  A: 

I always do like this (and I do it quite often):

I have an array of string or a TStringList containing the list-box items. Then, in Edit1Change I clear the Items property and add only those strings that match the text in the edit box.

Array Of String

If you work with an array of strings, such as

var
  arr: array of string;

that is initialized somehow, as in

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

then you can do

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;

This will only display those strings in the array that contain Edit1.Text; the string need not start with Edit1.Text. To accomplish this, replace

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

with

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

TStringList

In case of a TStringList, as in

var
  arr: TStringList;

and

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

you can do

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;

Case-Sensitivity

The above code uses case-sensitive matching, so that "bo" will not match "Boston", for instance. To make the code not sensitive to the case, write

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

instead of

if Pos(Edit1.Text, arr[i]) > 0 then
Andreas Rejbrand
that might work. the problem I see is that I don't know how many items there are in listbox. it's not fixed. it'll be hard to set the size of the array with SetLength. unless... can I use SetLength later to reset the length of the array? or it's better to use a TStringList?
Uri
Most people always work with the `TStringList`, but personally I want to do everything manually, so I always work with `array of string`. You can change the length of a dynamic array at any time by means of `SetLength`. If you increase the length, the old items will still be there.
Andreas Rejbrand
hmmm. i am trying with a tliststring. When I tried searching ALL the items disappear.Oh my bad, i was loading it wrong... however it's not working. I have a 2 files called: book 1 and book 2. when I search book it find the "bo" of a file called " places in boston" but that's it
Uri
got it, i just added Lowercase() to Pos(Lowercase(Edit1.Text), Lowercase(arr[i])) to make it case insensitive.thanks!
Uri
@Uri: Yes, I thought that was the problem, so I even updated my answer!
Andreas Rejbrand
A: 

What you are asking for can be implemented by hooking up the standard Win32 API IAutoComplete interface to a standard TEdit, no TListBox needed. It is not too difficult to hook up a TStrings object to IAutoComplete so it knows what strings are available for searching.

Remy Lebeau - TeamB