Making a ComboBox that autocompletes text as you type
Have you ever noticed how in Location boxes for browser windows and the Windows run box, whatever
you type is autocompleted for you if it already exists in the combobox? Have you ever wanted
to put this functionality into a combobox of your own and tried many times to get it to work?
In this TI, I will explain the (relatively simple) process of adding this autocomplete feature
to a TComboBox.
In order to add autocomplete features to a TComboBox, you need to trap the OnKeyDown and
OnChange events. In these events you will do all of the searching, replacing, and selecting.
The Win32 ComboBox control actually _does_ have autocomplete built into it, but it is not
always implemented. To help you out with this feature, the Win32 API has several messages:
CB_FINDSTRING Finds a string based on a case-insensitive search of the first
few letters.
CB_FINDSTRINGEXACT Finds the first list box string in a combo box that matches the
string specified.
CB_SELECTSTRING Searches the list of a combo box for an item that begins with the
characters in a specified string. If a matching item is found, it
is selected and copied to the edit control.
Because of the way TComboBox is designed, we will only be using CB_FINDSTRING.
In this example, I load some data from the customers.db table from BCDEMOS to populate the
list, then trap the OnKeyDown and OnChange events.
CB_FINDSTRING takes, as its first parameter (wParam), the index of the item before the start
of the search. Since we are searching the whole list, we set it to -1.
The second parameter is the address of the string to search for.
-------------Code--------------
//cb is the ComboBox
//lastKey is a private member of TForm1
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Table1->Open(); //get data from the table
Table1->First();
while (!Table1->Eof)
{
cb->Items->Add(Table1->FieldByName("Contact")->AsString);
Table1->Next();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
lastKey = Key; //get the last key the user hit in the ComboBox
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbChange(TObject *Sender)
{
String srch = cb->Text; //text to search for
if ((lastKey == 0x08) || (lastKey == VK_DELETE)) //if they hit backspace or delete,
{ //get out of here
lastKey = 0;
return;
}
lastKey = 0;
int ix = cb->Perform(CB_FINDSTRING,-1,(LPARAM)srch.c_str()); //find the string in the list
if (ix != CB_ERR)
{
cb->ItemIndex = ix; //set the ComboBox text accordingly
cb->SelStart = srch.Length();
cb->SelLength = (cb->Text.Length()-srch.Length()); //select the appropriate text
}
}
//---------------------------------------------------------------------------
|