以下示例使用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.
好問題,我打算用類似的東西在未來。 (用於電子郵件地址控制)。但是恐怕這對標準的TComboBox來說是不可能的。 – 2012-02-27 14:25:15
在這種情況下(技術上),「從一開始」和「不從一開始」之間有什麼區別? – teran 2012-02-27 14:46:40
你需要這樣的東西:http://stackoverflow.com/questions/7696075/need-a-combobox-with-filtering – 2012-02-27 15:10:29