Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to both autocomplete and limit to list with Delphi TComboBox

Suppose I want to select 'london' from a big list of UK towns

Setting

Combo1.AutoComplete := true;
Combo1.Style := csDropdown;

if I type 'l' followed by 'o', followed by 'n' it initially selects the first item starting with 'l' and then the first item starting with the two letters 'lo' and then the first starting with 'lon'. This is exactly the behaviour I want - which is good.

However I can also enter any text I like, whether it's in the list or not - this is bad.

Setting

Combo1.AutoComplete := true;
Combo1.Style := csDropdownList;

I can't enter any text I like but only select an item from the list - which is good.

But now if I type 'l' followed by 'o', followed by 'n' it initially selects the first item starting with 'l', then selects the first item starting with 'o' and the the first starting with 'n', instead of using all three letters and selecting the first item starting with 'lon'.

How can I achive both things at once?

ie I want to be limited to selecting items from the list but also be able to start typing and have it select on all the letters I have typed so far.

like image 577
user2834566 Avatar asked Oct 16 '25 18:10

user2834566


2 Answers

Use the second option

Combo1.AutoComplete := true;
Combo1.Style := csDropdownList;

and increase the autocomplete delay from the default 500 to something a little bigger to give the user time to type the second and third etc characters before the autocomplete kicks in.

like image 145
user2834566 Avatar answered Oct 18 '25 16:10

user2834566


Here is small "hack" to control text in the ComboBox in code:

uses ... StrUtils;

...

procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
var
  s, t: string;
  i, l: Integer;
  f: Boolean;
begin
  // Skip functional keys
  if Key < ' ' then
    Exit;

  // Get text which can be in the combo after key pressed
  i := ComboBox1.SelStart;
  l := ComboBox1.SelLength;
  t := ComboBox1.Text;
  s := Copy(t, 1, i) + Key + Copy(t, i + l + 1, Length(t));

  // Check is this text corresponds to the values list
  f := False;
  for i := 0 to ComboBox1.Items.Count - 1 do
    if StrUtils.StartsStr(s, ComboBox1.Items[i]) then
    begin
      f := True;
      Break;
    end;

  // If not - cancel key
  if not f then
    Key := #0;
end;

PS: It is for Combo1.Style := csDropdown; case

like image 34
Abelisto Avatar answered Oct 18 '25 17:10

Abelisto



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!