Announcement

Collapse
No announcement yet.

TMemo während der Eingabe

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TMemo während der Eingabe

    Hallo,

    Ich hab ein etwas kniffeliges Problem mit TMemo.

    Ich würde gerne während der Texteingabe in einem TMemo-Feld die Eingabe Wortweise prüfen und in einer Stringliste (Eine Art Wörterbuch) nachschlagen und die EIngabe vervollständigen.
    Ungefähr so:

    Ich tippe Text und nach Wortanfang prüfe ich ob es das Wort im Wörterbcuh gibt und schlage selektiert den Rest des Wortes vor. Wenn der nächste Buchstabe eingegeb wird fange ich wieder von vorne an bis ich ENTER drücke weil es das richtige Wort ist. So wie beim Autovervollständigen im Word.

    Ich hab schon herumexperimentiert bekomme aber keine vernünftige Version hin wie ich einen Text vervollständige indem ich ihn "blau" hinterlege. Auch das Wortweise auslesen funktioniert nicht wirklich. Denke es müßte irgendwie mit WM_Perform funktionieren aber da seh ich mich nicht wirklich raus.

    Hat irgendwer einen Denkanstoß für mich.

    DANKE
    Peter

  • #2
    Hallo,

    besser spät als nie :-)

    Ist tatsächlich etwas knifflig, habe aber nach einigem Tüfteln immerhin folgenden Code zustandegebracht (sieht gar nicht mal soo wild aus):

    <pre>unit Memoform;</pre>

    <pre>interface</pre>

    <pre>uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;</pre>

    <pre>type
    TForm1 = class(TForm)
    Memo1: TMemo; // Schreibfeld
    ListBox1: TListBox; // Wortliste
    ListBox2: TListBox; // Ergänzungsliste (Visible:=false zur Entwurfszeit!)
    procedure Memo1Change(Sender: TObject);
    procedure Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    private
    CWort:String; // Enthält den Beginn des aktuellen Wortes
    Auswahl:Boolean; // Verhindert das Einfügen des Zeilenumbruchs bei der Wortauswahl
    public
    end;</pre>

    <pre>var
    Form1: TForm1;</pre>

    <pre>implementation</pre>

    <pre>// ++++++++++++++++++++++ Nach jeder Änderung die Autovervollständigung starten ++++++++++++
    procedure TForm1.Memo1Change(Sender: TObject);
    var Trennzeichen:String;
    CPos,i,CLength,CLine,WLength:Integer;</pre>

    <pre>begin
    if Auswahl then begin // Löschen des Zeilenumbruchs (durch die Wortauswahl erforderlich)
    Auswahl:=False;
    CPos:=Memo1.Selstart; // Cursorposition merken, wird durch nächste Anweisung auf 0 gesetzt
    Memo1.Text:= copy(Memo1.Text,1,Memo1.Selstart-2) //Zeilenumbruch löschen
    +copy(Memo1.Text,Memo1.SelStart+Memo1.SelLength+1, length(Memo1.text));
    Memo1.SelStart:=CPos-2; // Cursor hinter ergänztes Wort setzen
    end
    else begin
    // =========================== Aktuelles Wort ermitteln ===========================
    Trennzeichen:=' ,.;:-!?"''()[]{}/\'#13#10; //Liste erweiterbar
    CWort:='';
    CPos:=Memo1.SelStart;
    while CPos>0 do
    if pos(Memo1.Text[CPos],Trennzeichen)>0 then CPos:=0 //Abbruchbedingung
    else begin
    CWort:=Memo1.Text[CPos]+CWort;
    dec(CPos)
    end;
    // =========================== Liste der Worte erzeugen ===========================
    Listbox2.Clear;
    for i:=0 to ListBox1.Items.count-1 do
    if pos(ansilowercase(CWort),ansilowercase(ListBox1.It ems[i]))=1 then ListBox2.Items.Add(ListBox1.Items[i]);
    // =========================== Liste ggf. anzeigen ===========================
    if ListBox2.Items.count>0 then begin
    // aktuelle Zeile und Textlänge im Memofeld ermitteln
    WLength:=0;
    CLength:=Length(Memo1.lines[0]);
    CLine:=1;
    while CLength<Memo1.SelStart do begin
    WLength:=WLength+Length(Memo1.lines[CLine-1]);
    CLength:=CLength+Length(Memo1.lines[CLine]);
    inc(CLine);
    end;
    // Einblendeposition berechnen
    Listbox2.top :=Memo1.top + abs(CLine*Memo1.Font.Height)+5;
    Listbox2.left:=Memo1.left+ canvas.Textwidth(copy(Memo1.lines[CLine-1],1,Memo1.Selstart-WLength));
    end;
    Listbox2.visible:=(ListBox2.Items.count>0);
    end;
    end;</pre>

    <pre>// ++++++++++++++ Auswahl durch Pfeil auf/ab-Tasten und Enter ++++++++++++++++++++++++++++++
    procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    var ErgText:String;
    CPos,i:Integer;
    begin
    if Listbox2.visible then
    case Key of
    VK_up : begin
    ListBox2.ItemIndex:=ListBox2.ItemIndex-1;
    if Listbox2.ItemIndex<0 then Listbox2.ItemIndex:=0;
    end;
    VK_down : begin
    ListBox2.ItemIndex:=ListBox2.ItemIndex+1;
    if Listbox2.ItemIndex>Listbox2.Items.count-1 then Listbox2.ItemIndex:=Listbox2.Items.count-1;
    end;
    VK_Return : begin
    i:=0;
    while not ListBox2.Selected[i] do inc(i);
    ErgText:=copy(ListBox2.Items[i],length(CWort)+1,Length(ListBox2.Items[i]));
    CPos:=Memo1.Selstart; // Cursorposition merken, wird durch nächste Anweisung auf 0 gesetzt
    Memo1.Text:= copy(Memo1.Text,1,Memo1.Selstart) // Ergänzung einfügen
    +ErgText
    +copy(Memo1.Text,Memo1.SelStart+Memo1.SelLength+1, length(Memo1.text));
    Memo1.SelStart:=CPos+length(ErgText); // Cursor hinter ergänztes Wort setzen
    Auswahl:=True; // Damit der Zeilenumbruch nicht zusätzlich geschrieben wird
    Listbox2.visible:=false;
    end;
    end;
    end;</pre>

    <pre>end.
    </pre>

    Voraussetzung hierbei sind ein Memofeld und zwei Listenfelder.
    Du mußt noch zur Entwurfszeit das Listenfeld1 mit ein paar Worten füllen (das Lexikon schreiben). Die passenden werden dann zur Laufzeit anhand des aktuellen Wortes im Memofeld zusammengesucht und im Listenfeld2 präsentiert.

    Die Version ist noch etwas buggy, was man vor allem bei mehreren Zeilen im Memofeld merkt, aber vielleicht hilft sie dir schon weiter.

    Gruß<br>
    Ale

    Comment


    • #3
      Soll es nicht unbedingt eine selbst geschriebene Komponente sein, einfach mal hier schauen:<br>
      AdvMemo: http://www.tmssoftware.com/<p>
      Schöne Grüße, Mario Noac
      Schöne Grüße, Mario

      Comment

      Working...
      X