需要一个带过滤功能的组合框

发布于 2024-12-09 02:06:46 字数 149 浏览 0 评论 0原文

我需要某种类型的组合框,它可以从数据库加载它的项目。当我在其中输入一些文本时,它应该过滤它的列表,只留下那些在某处有我的文本的项目(在开头、中间......)。并非所有我的数据集都具有过滤功能,因此无法使用它们。有没有现成的具有这种能力的组件?我尝试在 JVCL 中搜索,但没有成功。

I need some type of ComboBox which can load it's items from DB. While I type some text in to it, it should filter it's list, leaving only those items, that have my text somewhere (at the beginning, middle...). Not all my DataSet's have filtering capabilities, so it is not possible to use them. Is there any ready to use components with such abilities? I have tried to search in JVCL, but without luck.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

↘人皮目录ツ 2024-12-16 02:06:46

您可以尝试自定义常规组合框的自动完成功能。从数据库加载其项目很容易:

    ComboBox1.Items.Clear;   
    while not Table1.Eof do begin
      ComboBox1.Items.AddObject( Table1.FieldByName('Company').AsString,  
       TObject(Table1.FieldByName('CustNo').AsInteger) );
      Table1.Next;   
    end;

就单词中间匹配的自动完成而言,您可以尝试调整 这段代码。通过将 AutoComplete 设置为 true 来启用与 Items 中文本开头匹配的功能,并且在尝试编写自己的自动完成 OnChange 事件处理程序之前需要将其关闭。我建议您可以更安全地在回车键上进行匹配和选择,因为尝试即时执行此操作会使事情变得非常棘手,正如下面的代码将向您展示的那样:

这是我的基本版本:使用带有 onKeyDown 的常规组合框,和 onChange 事件,并将 AutoComplete 设置为 false,使用上面的代码填充它,这两个事件

procedure TForm2.ComboBox1Change(Sender: TObject);
var
  SearchStr,FullStr: string;
  i,retVal,FoundIndex: integer;
  ctrl:TComboBox;
begin
  if fLastKey=VK_BACK then
       exit;

  // copy search pattern
  ctrl := (Sender as TCombobox);
  SearchStr := UpperCase(ctrl.Text);
  FoundIndex := -1;
  if SearchStr<>'' then
  for i := 0 to ctrl.Items.Count-1 do begin
    if Pos(SearchStr, UpperCase(ctrl.Items[i]))>0 then
    begin
       FoundIndex := i;
       fsearchkeys := ctrl.Text;
       break;
    end;
  end;

  if (FoundIndex>=0) then
  begin
    retVal := ctrl.Perform(CB_SELECTSTRING, 0, LongInt(PChar(ctrl.Items[FoundIndex]))) ;

    if retVal > CB_Err then
    begin
      ctrl.ItemIndex := retVal;
      ctrl.SelStart := Pos(SearchStr,UpperCase(ctrl.Text))+Length(SearchStr)-1;
      ctrl.SelLength := (Length(ctrl.Text) - Length(SearchStr));
    end; // retVal > CB_Err

  end; // lastKey <> VK_BACK

end;

procedure TForm2.ComboBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  fLastKey := Key;
end;

假设列表的内容是“David Smith”和“Mark Smithers”。您输入 S,它会匹配 David Smith 姓氏的第一个字母。现在,它显示 David Smith 未选择“David S”部分,而选择了“mith”部分(以便您键入的下一个字符将替换自动完成部分,这是一种标准的自动完成技术)。请注意,上面的代码必须在您输入的 S 前面添加您未输入的“David”部分。如果你比我聪明得多,你可以找到一种方法来记住用户输入了“s”,然后可能是“m”,后面跟着更多的字母,最后输入了“Smithe”,匹配 Smithers,而不是总是大卫·史密斯。另请注意,您只能设置 SelStart 和 SelLength 来选择连续长度的字符串。

我提供的代码仅在项目列表不包含任何重复的子字符串时才有效。 Windows 通用控制组合框“自动完成”功能仅适用于前缀匹配,而不适用于中间字符串匹配,这是有充分理由的。

由于任何实现中间字符串匹配的内容都可能会绘制您输入的未选择的部分,并且由于该未选择的部分将位于中间字符串中,因此您可能需要从头开始编写自己的控件,而不是依赖于TComboBox 基本代码及其底层 MS 通用控件组合框功能。

You could try customizing the autocomplete functionality of a regular ComboBox. Loading its items from a DB is easy:

    ComboBox1.Items.Clear;   
    while not Table1.Eof do begin
      ComboBox1.Items.AddObject( Table1.FieldByName('Company').AsString,  
       TObject(Table1.FieldByName('CustNo').AsInteger) );
      Table1.Next;   
    end;

As far as the auto-complete for middle-of-word matching, you might try adapting this code. The functionality that matches at the beginning of the text in the Items is enabled by setting AutoComplete to true, and needs to be turned off before you try writing your own OnChange event handler that does auto-complete. I suggest that you could more safely do the match and selection on the enter key, because attempting to do it on the fly makes things quite hairy, as the code below will show you:

Here's my basic version: Use a regular combobox with onKeyDown, and onChange events, and AutoComplete set to false, use above code to populate it, and these two events

procedure TForm2.ComboBox1Change(Sender: TObject);
var
  SearchStr,FullStr: string;
  i,retVal,FoundIndex: integer;
  ctrl:TComboBox;
begin
  if fLastKey=VK_BACK then
       exit;

  // copy search pattern
  ctrl := (Sender as TCombobox);
  SearchStr := UpperCase(ctrl.Text);
  FoundIndex := -1;
  if SearchStr<>'' then
  for i := 0 to ctrl.Items.Count-1 do begin
    if Pos(SearchStr, UpperCase(ctrl.Items[i]))>0 then
    begin
       FoundIndex := i;
       fsearchkeys := ctrl.Text;
       break;
    end;
  end;

  if (FoundIndex>=0) then
  begin
    retVal := ctrl.Perform(CB_SELECTSTRING, 0, LongInt(PChar(ctrl.Items[FoundIndex]))) ;

    if retVal > CB_Err then
    begin
      ctrl.ItemIndex := retVal;
      ctrl.SelStart := Pos(SearchStr,UpperCase(ctrl.Text))+Length(SearchStr)-1;
      ctrl.SelLength := (Length(ctrl.Text) - Length(SearchStr));
    end; // retVal > CB_Err

  end; // lastKey <> VK_BACK

end;

procedure TForm2.ComboBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  fLastKey := Key;
end;

Suppose the contents of the list are "David Smith", and "Mark Smithers". You type S and it matches the first letter of the last name, in David Smith. Now it shows David Smith with the "David S" part not selected, and the "mith" part selected (so that the next characters you type will replace the auto completed portion, a standard auto-complete technique). Note that the above code has had to prefix the S you typed with the "David " part you didn't type. If you are a lot more clever than me, you can find a way to remember that the user typed "s" and then, maybe an "m", followed by some more letters, and eventually having typed "Smithe", match Smithers, instead of always David smith. Also note that you can only set the SelStart and SelLength to select a continuous length of a string.

The code I have provided will only work when the list of items never contains any repeated substrings. There are good reasons why the Windows Common Control combobox "autocomplete" functionality only works with prefix matching, and not mid-string matching.

Since anything that would implement mid-string matching should probably draw the part you typed in not-selected, and since that not-selected part would be in mid-string, you would probably need to write your own control from scratch and not rely on the TComboBox base code, and its underlying MS Common Controls combobox functionality.

梦忆晨望 2024-12-16 02:06:46

DevExpress 的“TcxExtLookupCombobox”具有此功能 - 甚至更多。但可能有点矫枉过正。

DevExpress' "TcxExtLookupCombobox" has this capability - and more. Might be overkill though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文