Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi AutoComplete für TMemo, TRichEdit uvm. (https://www.delphipraxis.net/125828-autocomplete-fuer-tmemo-trichedit-uvm.html)

Woodman 12. Dez 2008 15:53


AutoComplete für TMemo, TRichEdit uvm.
 
Liste der Anhänge anzeigen (Anzahl: 2)
Nachdem ich mir einen "Wolf" gesucht hatte und außer SynEdit nichts passendes gefunden habe (was mir für meine Zwecke etwas zu komplex ist), habe ich mir meine eigene TAutoComplete-Komponente geschrieben.
Ich wollte für eine eigene Anwendung eine AutoComplete-Funktion haben, ähnlich wie sie die Delphi-IDE bietet.

Die Unit "autocomplete" kann für Klassen verwendet werden, die auf TEdit basieren,
wie z.B. TMemo, TRichEdit, TEdit, TLabeledEdit usw.
Die Initialisierung geschieht z.B. folgender Maßen:
Delphi-Quellcode:
AutoComplete1 := TAutoComplete.Create(Form1,'TextDatei',Memo1);
Damit wird die Komponente 'Memo1' um AutoComplete erweitert.
Die Textdatei enthält das für Memo1 wichtige Wörterbuch.

In das Wörterbuch sollten nur Wörter eingetragen werden, die länger als 4 Zeichen sind.
AutoComplete reagiert erst ab 3 Zeichen Eingabe.

Ist für die Edit-Komponente ein Popup-Menu definiert, dann wird dieses um den
Menupunkt "Markierten Text in Wörterbuch übernehmen." erweitert

Wichtig: Durch AutoComlete werden die Ereignisbehandlungen 'OnChange', 'OnKeyDown', 'OnKeyPress' und 'OnContextPopup'überschrieben.
Sollten diese im Hauptprogramm benötigt werden, ist diese Lösung zunächst nicht einsetzbar.

In der ZIP-Datei befindet sich die Unit autocomplete.pas und das passende Testprogramm dazu.

Hier ein Auszug aus dem Testprogramm:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
   AutoComplete1 := TAutoComplete.Create(self,'worte.txt',Memo1);
   AutoComplete2 := TAutoComplete.Create(Form1,'plz.txt',LabeledEdit1);
   AutoComplete3 := TAutoComplete.Create(Form1,'words4.txt',RichEdit1);
   
end;
Wie man sieht, werden hier 3 Komponenten mit 'AutoComplete' erweitert.
Zugegeben: Das Beispiel mit dem LabeledEdit1 kann man auch mit TComboBox realisieren, aber mir ging es ja hauptsächlich um TMemo und eventuell um TRichEdit.
Das Beispiel für TMemo habe ich mit einer Textdatei hinterlegt, wie sie bei mir zum Einsatz kommt(Für ein Dia-Verwaltungsprogramm).
Bei dem LabeledEdit1 habe ich eine Postleitzahlendatei hinterlegt (ohne Gewähr :wink: )
Die RichEdit-Box reagiert vielleicht etwas träge. Das liegt daran, das ich hier versucht habe, TAutoComplete auszureizen: Die dazugehörige Textdatei 'words4.txt' ist über 2MB groß (über 150000 Zeilen).

Falls sich jemand wundert, warum ich RichEdit auf ein Panel gepackt habe und auf das Panel noch ein TabControl und darauf das Memo: Das hatte ganz einfach den Zweck, die Positionsfindung für AutoComplete zu testen, mit einem einfachen "ClientToParent" war es nicht getan...

Im beiliegenden Screenshot kann man das Testprogramm in Aktion sehen.

sx2008 13. Dez 2008 18:41

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Was mir nicht so gut gefällt, ist dass der Owner im Konstruktor mitgegeben werden muss.
Gerade dein Beispiel:
Delphi-Quellcode:
 AutoComplete2 := TAutoComplete.Create(Form1,'plz.txt',LabeledEdit1);
zeigt, dass man damit schwerzufindende Fehler begehen kann.
Folgendes Beispiel zeigt, dass man Formulare auch mit lokalen Variablen erstellen kann.
Delphi-Quellcode:
procedure Test;
var
  x : TForm1;
begin
  x := TForm1.Create(nil);
  x.ShowModal;
  x.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Fehler: Owner ist Form1 - richtig kann aber nur self sein
  AutoComplete := TAutoComplete.Create(Form1,'plz.txt',LabeledEdit1);
end;
Um dieses Problem aus der Welt zu schaffen, würde ich folgende Änderung vorschlagen:
Delphi-Quellcode:
constructor TAutoComplete.Create(const Edit: TControl; const TxtFile: String);
begin
  Assert(Assigned(Edit));
  Inherited Create(Edit.Owner);      // gleicher Owner, den auch Edit hat
  Parent := Edit.Parent;             // dito *)
Bei der Zeile mit dem *) könnte sich jetzt ein Problem ergeben, weil vorher der Parent das Formular war und jetzt kann es auch eine Groupbox sein.
Dann kann man aber so lange über Parent nach "oben" gehen, bis man auf dem Formular gelandet ist.
Delphi-Quellcode:
var
  tmp : TControl;
begin
  tmp := Edit.Parent;
  while Assigned(tmp.Parent) do tmp := tmp.Parent;
  Parent := tmp;

SirThornberry 13. Dez 2008 19:10

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Die Idee an sich finde ich gut. Was ich nicht so toll finde ist eben die Umsetzung das es eine Datei sein muss und das die Ereignisse dann nicht mehr nutzbar sind.
Auch die minimale Anzahl von Zeichen, finde ich, sollte einstellbar sein.

Insgesamt soll das heißen: Bleib an der Idee dran und versuche es zu verfeiern/verbessern.

Woodman 14. Dez 2008 17:21

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Zitat von sx2008
Was mir nicht so gut gefällt, ist dass der Owner im Konstruktor mitgegeben werden muss.
Gerade dein Beispiel:
Delphi-Quellcode:
 AutoComplete2 := TAutoComplete.Create(Form1,'plz.txt',LabeledEdit1);
zeigt, dass man damit schwerzufindende Fehler begehen kann.
Folgendes Beispiel zeigt, dass man Formulare auch mit lokalen Variablen erstellen kann.

Verzeih' einem Anfänger, das ich Dir nicht ganz folgen kann :wall:
Was ist falsch daran, den Owner mit zu geben?
Ich will ja gerade, das die unterste Komponente (Form1) der Owner ist. Gerade in meinem Beispiel, bei dem das TMemo auf einem TPanel und dieses wiederum auf einem TTabControl sitzt ist es wichtig, das als Parent für den TListView (TAutoComplete) die Form ist.
Zitat:

Zitat von sx2008
...
Bei der Zeile mit dem *) könnte sich jetzt ein Problem ergeben, weil vorher der Parent das Formular war und jetzt kann es auch eine Groupbox sein.

Eben, deswegen sorge ich dafür, das der Parent von TAutoComplete immer das Formular ist.

himitsu 14. Dez 2008 17:33

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Wichtig: Durch AutoComlete werden die Ereignisbehandlungen 'OnChange', 'OnKeyDown', 'OnKeyPress' und 'OnContextPopup'überschrieben.
Sollten diese im Hauptprogramm benötigt werden, ist diese Lösung zunächst nicht einsetzbar.
dann überschreib die Eigenschaften doch nicht einfach!

ließ die vorherrigen Werte aus und ruf (falls da schon etwas eingetragen ist) dieses in deiner Klasse auf.

Woodman 14. Dez 2008 17:36

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Zitat von SirThornberry
Die Idee an sich finde ich gut.

Danke :-D
Zitat:

Zitat von SirThornberry
Was ich nicht so toll finde ist eben die Umsetzung das es eine Datei sein muss

Könntest Du mir bitte das näher erläutern - ich verstehe jetzt nicht was Du meinst. :oops:
Zitat:

Zitat von SirThornberry
und das die Ereignisse dann nicht mehr nutzbar sind.

Ich könnte natürlich falls eine Eventbehandlung schon besetzt ist, diese mit übernehmen.
Aber: Welche Eventbehandlung führe ich zu erst aus, die vom Hauptprogramm oder die von TAutoComplete? Ober "beißen" sich die beiden Eventbehandlunge gar?
Ich fürcht, das muss jeder individuell beurteilen und in seinem Programm anpassen.
Zitat:

Zitat von SirThornberry
Auch die minimale Anzahl von Zeichen, finde ich, sollte einstellbar sein.

Nun ja, im Programm kannst Du es ja einstellen. :P

Zitat:

Zitat von SirThornberry
Insgesamt soll das heißen: Bleib an der Idee dran und versuche es zu verfeiern/verbessern.

EDIT:
Zitat:

Zitat von himitsu
Zitat:

Wichtig: Durch AutoComlete werden die Ereignisbehandlungen 'OnChange', 'OnKeyDown', 'OnKeyPress' und 'OnContextPopup'überschrieben.
Sollten diese im Hauptprogramm benötigt werden, ist diese Lösung zunächst nicht einsetzbar.
dann überschreib die Eigenschaften doch nicht einfach!

ließ die vorherrigen Werte aus und ruf (falls da schon etwas eingetragen ist) dieses in deiner Klasse auf.

siehe oben.

himitsu 14. Dez 2008 18:54

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Könntest Du mir bitte das näher erläutern - ich verstehe jetzt nicht was Du meinst.
z.B. daß man statt dem Dateinamen auch einfach nur eine StringList, oder einen Stream übergeben kann.

sx2008 15. Dez 2008 01:42

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Zitat von Woodman
Verzeih' einem Anfänger, das ich Dir nicht ganz folgen kann :wall:
Was ist falsch daran, den Owner mit zu geben?

Du hast ein Klasse TForm1 und eine globale Variable Form1.
Solange es nur ein Formular dieser Klasse gibt ist alles in Ordnung.
Wenn es aber mehrere Formulare der gleichen Klasse gibt, dann können ja nicht alle in der Variable Form1 gespeichert sein.
Das würde dann bedeuten, dass die Autocomplete Komponente auf das falsche Formular zugreift.
Es könnte sogar sein, dass die Variable Form1 = nil ist.
Man kann sich vorstellen, dass das sehr unangenehm werden kann.

Woodman 15. Dez 2008 08:55

Re: AutoComplete für TMemo, TRichEdit uvm.
 
Zitat:

Zitat von himitsu
Zitat:

Könntest Du mir bitte das näher erläutern - ich verstehe jetzt nicht was Du meinst.
z.B. daß man statt dem Dateinamen auch einfach nur eine StringList, oder einen Stream übergeben kann.

Du meinst, das die Keywords erst während des Programmlaufes dynamisch erzeugt werden?
Ich denke, das kann sich jeder selber einbauen, letztendlich wird die Datei in eine StrinList geladen. Dann würde natürlich der Event "OnContextPopup" wieder frei, weil dann markierte Wörter nicht mehr abgespeichert werden können.

SirThornberry 15. Dez 2008 09:06

Re: AutoComplete für TMemo, TRichEdit uvm.
 
der Vorteil eines Streams bzw. einer Stringlist anstelle einer Datei ist das mehrere Komponenten das gleiche AutoComplete verwenden könnten ohne das alles 2 mal im Speicher ist.

[edit=TBx]Da war ein Wort zuviel ;-) Mfg, TBx[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:43 Uhr.
Seite 1 von 4  1 23     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz