如何使用全文搜索自动完成支持制作组合框?

Bre*_*tor 32 delphi autocomplete autosuggest

我希望用户能够输入项目中的第二个或第三个单词,TComboBox并使该项目显示在AutoSuggest下拉选项中

例如,组合框包含以下项目:

  • 约翰布朗先生
  • 阿曼达布朗夫人
  • Brian Jones先生
  • 萨曼莎史密斯夫人

当用户键入"Br"时,下拉列表显示:

  • 约翰布朗先生
  • 阿曼达布朗夫人
  • Brian Jones先生

当用户输入"Jo"时,下拉列表显示:

  • 约翰布朗先生
  • Brian Jones先生

问题是该AutoSuggest功能仅包括下拉列表中以用户输入内容开头的项目,因此在上面的示例中,下拉列表中不会显示任何内容.

是否可以使用IAutoComplete接口和/或其他相关接口来解决此问题?

TLa*_*ama 33

以下示例使用TComboBox组件的插入类.从原始类的主要区别是,项目被存储在单独的StoredItems属性,而不是
Items作为通常(使用,因为简单的).

StoredItems正在被观看的OnChange事件,只要你(通过添加或从该字符串列表中删除例如)更改,当前的过滤器将反映甚至当组合
列表掉了下来.

这里的要点是捕获每当组合编辑文本被更改但尚未呈现时发送的WM_COMMAND消息通知CBN_EDITUPDATE.当它到达时,您只需在StoredItems列表中搜索您在组合编辑中输入的内容并Items使用匹配填充属性.

对于文本搜索使用,ContainsText因此搜索不区分大小写.忘记提及,
AutoComplete功能必须关闭,因为它有自己的,不受欢迎的逻辑为此目的.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, StrUtils, ExtCtrls;

type
  TComboBox = class(StdCtrls.TComboBox)
  private
    FStoredItems: TStringList;
    procedure FilterItems;
    procedure StoredItemsChange(Sender: TObject);
    procedure SetStoredItems(const Value: TStringList);
    procedure CNCommand(var AMessage: TWMCommand); message CN_COMMAND;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property StoredItems: TStringList read FStoredItems write SetStoredItems;
  end;

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TComboBox.Create(AOwner: TComponent);
begin
  inherited;
  AutoComplete := False;
  FStoredItems := TStringList.Create;
  FStoredItems.OnChange := StoredItemsChange;
end;

destructor TComboBox.Destroy;
begin
  FStoredItems.Free;
  inherited;
end;

procedure TComboBox.CNCommand(var AMessage: TWMCommand);
begin
  // we have to process everything from our ancestor
  inherited;
  // if we received the CBN_EDITUPDATE notification
  if AMessage.NotifyCode = CBN_EDITUPDATE then
    // fill the items with the matches
    FilterItems;
end;

procedure TComboBox.FilterItems;
var
  I: Integer;
  Selection: TSelection;
begin
  // store the current combo edit selection
  SendMessage(Handle, CB_GETEDITSEL, WPARAM(@Selection.StartPos),
    LPARAM(@Selection.EndPos));
  // begin with the items update
  Items.BeginUpdate;
  try
    // if the combo edit is not empty, then clear the items
    // and search through the FStoredItems
    if Text <> '' then
    begin
      // clear all items
      Items.Clear;
      // iterate through all of them
      for I := 0 to FStoredItems.Count - 1 do
        // check if the current one contains the text in edit
        if ContainsText(FStoredItems[I], Text) then
          // and if so, then add it to the items
          Items.Add(FStoredItems[I]);
    end
    // else the combo edit is empty
    else
      // so then we'll use all what we have in the FStoredItems
      Items.Assign(FStoredItems)
  finally
    // finish the items update
    Items.EndUpdate;
  end;
  // and restore the last combo edit selection
  SendMessage(Handle, CB_SETEDITSEL, 0, MakeLParam(Selection.StartPos,
    Selection.EndPos));
end;

procedure TComboBox.StoredItemsChange(Sender: TObject);
begin
  if Assigned(FStoredItems) then
    FilterItems;
end;

procedure TComboBox.SetStoredItems(const Value: TStringList);
begin
  if Assigned(FStoredItems) then
    FStoredItems.Assign(Value)
  else
    FStoredItems := Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  ComboBox: TComboBox;
begin
  // here's one combo created dynamically
  ComboBox := TComboBox.Create(Self);
  ComboBox.Parent := Self;
  ComboBox.Left := 10;
  ComboBox.Top := 10;
  ComboBox.Text := 'Br';

  // here's how to fill the StoredItems
  ComboBox.StoredItems.BeginUpdate;
  try
    ComboBox.StoredItems.Add('Mr John Brown');
    ComboBox.StoredItems.Add('Mrs Amanda Brown');
    ComboBox.StoredItems.Add('Mr Brian Jones');
    ComboBox.StoredItems.Add('Mrs Samantha Smith');
  finally
    ComboBox.StoredItems.EndUpdate;
  end;

  // and here's how to assign the Items of the combo box from the form 
  // to the StoredItems; note that if you'll use this, you have to do
  // it before you type something into the combo's edit, because typing 
  // may filter the Items, so they would get modified
  ComboBox1.StoredItems.Assign(ComboBox1.Items);
end;    

end.
Run Code Online (Sandbox Code Playgroud)

  • 这是太棒了.谢谢TLama (4认同)