Delphi和列表框项的显示

3
我将使用一个列表框来显示文件名的简单列表。我还有一个编辑组件,可以通过简单的搜索来搜索这些项目:
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;

现在,有没有一种方法可以“有选择地”在列表框上显示项目?我的意思是,如果我搜索以“hello”开头的项目,则只有那些以hello开头的项目将被显示,要么使不符合条件的项目变暗,要么完全设置为不可见。 是否有一种方法可以在列表框中执行此操作? 谢谢!
哦,这是Delphi 7...
2个回答

8

我经常这样做(而且我经常这样做):

我有一个包含列表框项的字符串数组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

可能会起作用。我看到的问题是我不知道列表框中有多少项。它不是固定的。使用SetLength设置数组的大小将很困难。除非...我可以稍后使用SetLength重置数组的长度吗?或者最好使用TStringList? - Uri
大多数人总是使用TStringList,但我个人想要手动完成所有操作,所以我总是使用array of string。您可以通过SetLength随时更改动态数组的长度。如果您增加长度,旧项目仍将存在。 - Andreas Rejbrand
嗯,我正在尝试使用TListString。当我尝试搜索时,所有项目都消失了。 哦,我的错,我加载它的方式不对...但是它还是不起作用。我有两个文件,分别叫做:书1和书2。当我搜索“book”时,它只能找到一个名为“places in boston”的文件中的“bo”。 - Uri
明白了,我刚刚在Pos(Lowercase(Edit1.Text), Lowercase(arr[i]))中添加了Lowercase()以使其不区分大小写。谢谢! - Uri
@Uri:是的,我也认为那是问题所在,所以我甚至更新了我的答案! - Andreas Rejbrand

2
您所要求的可以通过将标准Win32 API IAutoComplete 接口连接到标准的TEdit来实现,不需要 TListBox。将 TStrings 对象连接到 IAutoComplete 并让其知道可用于搜索的字符串也并不太难。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接