![]() |
Komponente ComboBox mit AutoFill-Funktion
Hallo Leute,
ich nutze seit längerer Zeit eine Funktion, um ComboBoxen automatisch während der Eingabe zu füllen, dh. man tippt ein Zeichen, und über ein in OnChange verankertes Unterprogramm wird in den Items nach dem ersten passenden Eintrag gesucht. Wird einer gefunden, wird der Eintrag in ComboBox.Text aufgefüllt und markiert. Mit dem nächsten Zeichen wiederholt sich das Ganze. Nachteil: Man muß bei jeder verwendeten ComboBox in KeyDown ein globale Variable LastKey mit key:word belegen, um diese dann in OnChange auszuwerten. Funktioniert, ist aber lästig. Nun habe ich eine Komponente erzeugt, die das auch macht, ohne daß ich immer die gleichen Prozeduren hinterlegen muß. Da es sich um meine erste eigene Komponente handelt, stelle ich das Ergebnis hier zur Diskusion zur Verfügung. Vielleicht sind ja noch ein paar Verbesserungen oder/und sinnvolle Erweiterungen möglich.
Delphi-Quellcode:
mfg
unit ComboBoxAF; //ComboBox AutoFill
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TComboBoxAF = class(TComboBox) private { Private-Deklarationen } FAutoFill : Boolean; FLastKey : word; FOnKeyDown : TKeyEvent; function GetLastKey : word; procedure SetLastKey(key : word); function GetAutoFill : Boolean; procedure SetAutoFill(value : Boolean); protected { Protected-Deklarationen } procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure Change; override; public { Public-Deklarationen } constructor Create(aOwner: TComponent); override; Destructor Destroy; override; property OnKeyDown : TKeyEvent read FOnKeyDown write FOnKeyDown; published { Published-Deklarationen } property LastKey : word read GetLastKey write SetLastKey; property AutoFill : Boolean read GetAutoFill write SetAutoFill; end; procedure Register; implementation procedure TComboBoxAF.Change; var srch : string; ix : integer; begin if Focused and AutoFill then begin srch := Text; if LastKey = $08 then begin LastKey := 0; end else begin LastKey := 0; ix := Perform(CB_FINDSTRING, -1, LongInt(PChar(srch))); if ix > CB_ERR then begin ItemIndex := ix; SelStart := Length(srch); SelLength := Length(Text) - length(srch); end; end; end; Inherited; end; procedure TComboBoxAF.KeyDown(var Key: Word; Shift: TShiftState); begin Inherited; // KeyDown(Key, Shift); FLastKey := key; end; function TComboBoxAF.GetLastKey : word; begin Result := FLastKey; end; procedure TComboBoxAF.SetLastKey(key : word); begin FLastKey := key; end; function TComboBoxAF.GetAutoFill : Boolean; begin Result := FAutoFill; end; procedure TComboBoxAF.SetAutoFill(value : Boolean); begin FAutoFill := value; end; constructor TComboBoxAF.Create(aOwner: TComponent); begin inherited Create(aOwner); FLastKey := 0; FAutoFill := true; end; Destructor TComboBoxAF.Destroy; Begin inherited Destroy; End; procedure Register; begin RegisterComponents('Beispiele', [TComboBoxAF]); // end; end. eddy |
Hier mal die Lösung, welche ich vor Monaten auf D3K veröffentlicht habe. (Sorry, habe z.Z. gerade keine .pas Version hier rumzuliegen und war zu faul Notepad zu öffnen). ;)
Vollständiger Artikel: ![]()
Delphi-Quellcode:
...:cat:...
unit FillComboBox;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFillComboBox = class(TComboBox) private FAutomaticFillin: Boolean; procedure SetAutomaticFillin(const Value: Boolean); protected procedure ComboWndProc( var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer ); override; public published constructor Create(AOwner: TComponent); override; property AutomaticFillin: Boolean read FAutomaticFillin write SetAutomaticFillin default True; end; procedure Register; implementation procedure Register; begin RegisterComponents('Standard', [TFillComboBox]); end; { TFillComboBox } procedure TFillComboBox.ComboWndProc( var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer ); var I: Integer; CurrentText: String; begin inherited ComboWndProc(Message, ComboWnd, ComboProc); // skip processing, if turned off if not FAutomaticFillin then Exit; // first check whether the backspace key was pressed, we do not fill in // in such case! if Message.Msg = WM_CHAR then begin // all characters from 32 (Space) through 127 (Upper ANSI) are matched if TWMChar(Message).CharCode in [$20..$7F] then begin // fill in the rest of the text // save the current text, the user has typed CurrentText := Text; // get the first string, matching the text partially I := SendMessage(Handle, CB_FINDSTRING, -1, LongInt(PChar(CurrentText))); if I >= 0 then begin // match found! // load matching text, I is the position of the matching string Text := Items.Strings[I]; // select the text beyond the text typed SelStart := Length(CurrentText); SelLength := Length(Text) - Length(CurrentText); end; end; end; end; constructor TFillComboBox.Create(AOwner: TComponent); begin inherited Create(AOwner); FAutomaticFillin := True; end; procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean); begin FAutomaticFillin := Value; end; end. |
Hallo sakura,
habe Deine Version soeben adaptiert, funktioniert auch unter Delphi 5. Kürzerer Quellcode ist immer effektiver. mfg eddy |
Zitat:
Wozu dient eigentlich die Eigenschaft LastKey in Deiner Version? ...:cat:... |
Hallo sakura,
LastKey ist reine Übernahme aus vorangegangener Version (irgendwo aus dem Internet), die nicht als eigene Komponente definiert war, sondern mit der Standardversion funktioniert. In OnKey wurde da immer LastKey mit Key ersetzt und in OnChange wurde LastKey ausgewertet. Habe das ganze nie ohne LastKey probiert. Jetzt würde mich nur noch interessieren, wie ich der Komponente eine anderes Icon zuordnen kann. Irgendwo habe ich das schon als Frage gesehen, aber wo nur .... ?? :mrgreen: mfg eddy |
Ist eigentlich ganz einfach: Du musst eine Resource-Datei (DCR) (z.B. mit Borlands Image Editor, im Tools/Werkzeuge Menü) erstellen, welche genau wie die Unit heisst, welche ein Bitmap (24x24 Pixel) für Deine Komponente enthält. Die Bitmap-Resource muss genauso wie Deine Komponente heissen. Wenn Du jetzt Deine Unit für die Komponente in ein Package einbindest, bindet Delphi die DCR-Datei automatisch mit ein und installiert das Bild in der Palette.
...:cat:... |
Hallo sakura,
vielen Dank, Du hast mich auf die richtige Spur geführt. Leider bin ich nicht zurechtgekommen. Unter ![]() mfg eddy |
Zitat:
...:cat:... |
Hallo sakura,
mein Fehler! Ich glaube, alles so gemacht zu haben, wie Du es beschrieben hast, aber Delphi hat trotzdem nicht mein Icon verwendet, sondern weiterhin das Standard-ComboBox-Icon. Auf der oben angegebenen Seite steht: "Jetzt wurde das Ressourcenfenster um weitere Einträge erweitert. Unser Bitmap ist "Bitmap1". Dieses müssen wir erst mal in "TBeispielComp" umbenennen, weil unsere Komponente ja die Klasse "TBeispielComp" ist. Per Doppelklick auf den jetzt "TBeispielComp" heißenden Eintrag lässtsich das Symbol bearbeiten." Und diese Kleinigkeit muß man wissen. Nachdem ich "Bitmap1" umbenannt habe in "TComboBoxAF" (AF = AutoFill) wurde von Delphi beim Compilieren auch das von mir gewünschte Icon verwendet. Und nachdem ich nun weiß, wie es geht, kann ich Deine bis dato ignorierten Worte: Zitat:
mfg eddy |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz