2007. február 6., kedd

How to set the item index in an alpha sorted TComboBox when searching incrementally


Problem/Question/Abstract:

I have some alpha sorted items in a combo box (style csDropDown). When the user types in text, the combo box incrementally searches but it does not set the itemindex property. Is there a way of making it do this?

Answer:

You could use the OnChange handler to perform a CB_FINDSTRING with the current edit text, then set the itemindex to the found item. But that is disruptive to typing, if the found item is not the one the user wants he has no way to change it, since each change triggers OnChange, which again finds the item. So you have to invest considerably more effort into this. Attach these handlers to the OnKeyPress and the OnChange event of the combobox, that seems to work fairly well.

procedure TForm1.ComboBox1Change(Sender: TObject);
var
  oldpos: Integer;
  item: Integer;
begin
  with sender as TComboBox do
  begin
    oldpos := selstart;
    item := Perform(CB_FINDSTRING, -1, lparam(Pchar(text)));
    if item >= 0 then
    begin
      onchange := nil;
      text := items[item];
      selstart := oldpos;
      sellength := gettextlen - selstart;
      onchange := combobox1change;
    end;
  end;
end;

procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
var
  oldlen: Integer;
begin
  if key = #8 then
    with sender as TComboBox do
    begin
      oldlen := sellength;
      if selstart > 0 then
      begin
        selstart := selstart - 1;
        sellength := oldlen + 1;
      end;
    end;
end;

This works with Win2000, but on a Win98 machine, the ItemIndex is getting set incorrectly after the first search. To make it work under both Win2000 and Win98, you could do something like this:

procedure TMainForm.ComboBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  s: string;
begin
  if key = VK_RETURN then
  begin
    s := TComboBox(Sender).Text;
    {The search doesn't work in Win 98 with DroppedDown set to true}
    TComboBox(Sender).DroppedDown := false;
    TComboBox(Sender).Text := s;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése