Geschrieben von holland am 03.07.2006, 21:20

ComboBox-Autocomplete

Wir sehen es in vielen Programmen.
Ein Benutzer "betritt" eine ComboBox schreibt einen Buchstaben hinein und wie von Geisterhand wird der erste passende Eintrag angezeigt.
Wenn er weiter schreibt wird evtl. der nächste passende gezeigt oder wenn keiner paßt nichts weitergeschrieben.

Komischerweise ist dieses Verhalten nicht grundsätzliches ComboBox-Verhalten. Die ComboBox kennt keine Eigenschaft die man setzen kann um sie "mal eben schnell" autocomplete-fähig zu machen.

Ich habe mir für dieses Problem eine eigene Routine programmiert welche ich hier vorstellen möchte.

Als erstes lagern wir folgende Funktion aus:
AnsiString __fastcall Form1::FindItem(TStringList *sl AnsiString stri int lensl)
{
AnsiString puffer;
int rueckgabe;
int z=0;
while (z<=lensl)
{
puffer = sl->Strings[z];
if(UpperCase(puffer).AnsiPos(UpperCase(stri)) > 0 )
return puffer;
z++;
}
return stri;
}

Dieser Funktion wird eine StringListe mit
1. allen Einträgen der betreffenden ComboBox
2.die momentan vom Benutzer eingegebenen Zeichen (stri) und
3.die Länge der Stringliste (lensl)
übergeben.
Daraufhin sucht sich diese Funktion den ersten passenden Eintrag und gibt diesen als AnsiString an die aurufende Funktion zurück.

Den Aufruf coden wir in das "Key-Up"-Ereignis einer ComboBox!
void __fastcall TfrmAuftrag::ComboBox1KeyUp(TObject *Sender WORD &Key
TShiftState Shift)
{
TStringList *sl = new TStringList;
int i= ComboBox1->Items->Count;
int laengeeingabe=ComboBox1->Text.Length();
int z=0;

if (Key!=8)
{
while (z<=i)
{
sl->Add(ComboBox1->Items->Strings[z]);
z++;
}
ComboBox1->Text = FindItem(sl ComboBox1->Text i);
ComboBox1->SelStart=laengeeingabe;
ComboBox1->SelLength=ComboBox1->Text.Length()-laengeeingabe;
}
delete sl;
}

Hier passiert folgendes:
Wenn nicht die Backspace-Taste (IF (KEY!=8) gedrückt wurde wird der Code ausgeführt. Das ist wichtig wenn sich der Benutzer einmal verschrieben hat und in der Box "zurück" möchte. Ohne diese Prüfung käme der Benutzer NICHT mehr zurück!
Nach dem Erstellen der StringListe wird der Integer int i= ComboBox1->Items->Count; mit der Anzahl der Einträge der ListBox "aufgeladen".
Dann wird der Integer int laengeeingabe=ComboBox1->Text.Length(); mit der Länge des Textes der vom Benutzer in die Box geschrieben wurde gefüllt .
Somit können wir die StringListe mit allen ComboBox-Einträgen füllen und die Funktion "FindItem" aufrufen.
Jetzt setzen wir noch mit den SEL-Methoden die Markierung und fertig!
Wichtig ist am Ende mit "delete" die StringListe wieder aus dem Speicher zu kegeln weil diese sonst zäh im Speicher bleibt. Und wir wollen ja nicht daß die User meckern weil wir ein speicherfressendes Proggi gecoded haben ;-)

Bewertung Anzahl