В следующем примере используется вставленный класс компонента TComboBox
. Основное отличие от исходного класса заключается в том, что элементы хранятся в отдельном свойстве StoredItems
вместо
_ 3_ как обычно (используется для простоты).
StoredItems
отслеживаются событием OnChange
и всякий раз, когда вы меняете их (например, добавляя или удаляя из этого списка строк), текущий фильтр будет отражать их, даже когда комбинированный список
выпадает.
Главное здесь - поймать WM_COMMAND
уведомление о сообщении CBN_EDITUPDATE
, который отправляется всякий раз, когда текст комбинированного редактирования изменяется, но еще не отображается. Когда он поступит, вы просто выполните поиск в StoredItems
списке того, что вы ввели при редактировании комбо, и заполните _ 9_ с совпадениями.
Для текстового поиска используется 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.
person
TLama
schedule
27.02.2012
IAutoComplete
интерфейс не поддерживает полнотекстовый поиск, работает только с текстом с самого начала. Единственный способ - ИМХО реализовать самостоятельно. Даже такие сообщения, какCB_FINDSTRING
, не учитываются при совпадении строк где-либо еще, кроме как с начала. - person TLama   schedule 29.02.2012IAutoComplete2
на включениеACO_AUTOSUGGEST
, он сделает это ... спасибо. - person EMBarbosa   schedule 29.02.2012.pas
файла. Я не уверен, где они это реализовали, поэтому я не ставлю это как ответ. Попробуйте это. - person EMBarbosa   schedule 29.02.2012TComboBox
. - person TLama   schedule 01.03.2012