Memo Text-Markierung nicht erwünscht

Für Fragen von Einsteigern und Programmieranfängern...

Memo Text-Markierung nicht erwünscht

Beitragvon Aliobaba » 6. Dez 2018, 10:25 Memo Text-Markierung nicht erwünscht

Hallo,

Ich möchte gerne per Doppelklick ein einzelnes Wort aus einem Memo Feld zur weiteren Verarbeitung "heraus kopieren".
Dies funktioniert mit dem unten gezeigten Code auch wunderbar.
Leider zeigt das Memo-Feld nach dieser Aktion ein unerwünschtes Verhalten, das ich gerne abstellen würde:
Immer wenn ich mit dem Mauszeiger aus dem "Showmessage-Feld" wieder in das Memo-Feld komme, dann wird der Text im Memo-Feld ab de Position "SelStart" markiert, als würde ich mit gedrückter linker Maustaste einen Textbereich markieren.

Wie kann ich dieses Verhalten des Memo-Feldes ausschalten?

Danke!
Aliobaba

Code: Alles auswählen
 procedure TF_Text.NMemoTextDblClick(Sender: TObject);
 var
   sss : string;
 begin
    sss := F_Text.Wort_extrahieren ( NMemoText , NMemoText.SelStart ) ;
    Showmessage (sss);
 end;
 
 Function TF_Text.Wort_extrahieren ( A_Memo : TMemo ; A_Selstart : integer ) : string;
 var
   i,  selbeginn : integer;
   txt, s : WideString;
 begin
     result := '';
     txt := UTF8Decode(A_Memo.Text);
     selbeginn := A_Selstart;
     i := A_Memo.SelStart;
     s := '';
     repeat
       result := s + result;
       s := Copy(txt, i, 1);
       Dec(i);
     until (s <= ' ') or (i < 0);
     i := A_Selstart + 1;
     s := '';
     repeat
       result := result + s;
       s := Copy(txt, i, 1);
       Inc(i);
     until (s <= ' ') or (s = '');
   end;                 
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )
Aliobaba
 
Beiträge: 349
Registriert: 1. Mai 2012, 08:11

Beitragvon braunbär » 6. Dez 2018, 15:41 Re: Memo Text-Markierung nicht erwünscht

Ein ähnliches Problem, mögicherweise genau das gleiche,tritt bei einem Stringgrid mit Spalten vom Typ cbsCheckboxColumn auf.
Nach dem Kicken auf ein Checkbox-Feld werden Gridfelder markiert, wenn man mit der Maus über das Grid fährt.
Zuletzt geändert von braunbär am 6. Dez 2018, 18:29, insgesamt 1-mal geändert.
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon theo » 6. Dez 2018, 15:43 Re: Memo Text-Markierung nicht erwünscht

Habe deinen Code nicht studiert, deshalb nur die Antwort auf die Frage:
Code: Alles auswählen
Memo.SelLength:=0;

müsste reichen, um die Auswahl zurückzusetzen.
theo
 
Beiträge: 8070
Registriert: 11. Sep 2006, 18:01

Beitragvon wp_xyz » 6. Dez 2018, 15:46 Re: Memo Text-Markierung nicht erwünscht

Funktioniert bei mir einwandfrei (Laz trunk, fpc 3.0.4, 32 bit, auf Windows 10, 64 bit). Auch ohne theos Vorschlag. Welche Versionen/Betriebssystem hast du?

Übrigens: In "NMemoTextDblClick" rufst du das Wort-Extrahieren auf als "F_Text.Wort_extrahieren". Auch wenn der Compiler hier nicht meckert und diese Zeile keinen Fehler verursacht, ist das falsch. Man darf nie die Formular-Variable im Klassen-Code verwenden, denn dann funktioniert die Methode nur, wenn es dieses Formular mit exakt diesem Namen auch gibt. "Wort_extrahieren" ist eine Methode der Klasse "TF_Text" und kann innerhalb dieser Klasse von überall aus aufgerufen werden, ohne weitere Zusätze, und egal wie die Instanz der Klasse heißt. Richtig ist es also folgendermaßen:
Code: Alles auswählen
procedure TF_Text.NMemoTextDblClick(Sender: TObject);
 var
   sss : string;
 begin
    sss := Wort_extrahieren ( NMemoText , NMemoText.SelStart ) ;    // <---- ohne "F_Text."
    Showmessage (sss);
 end;
wp_xyz
 
Beiträge: 2696
Registriert: 8. Apr 2011, 08:01

Beitragvon braunbär » 6. Dez 2018, 18:05 Re: Memo Text-Markierung nicht erwünscht

Ich habe es jetzt ausprobiert und kann das falsche Verhalten im Memofeld auch nicht nachvollziehen.

Dein Wort_Extrahieren ist übrigens unnötig kompliziert. Per Doppelklick wird ohnehin ein ganzes Wort selektiert (allerdings inkl. nachfolgender Leerstellen, die man vermutlich entfernen muss), eigentlich ist die Funktion ein Einzeiler:

Code: Alles auswählen
 
Function TF_Text.Wort_extrahieren (A_Memo : TMemo) : string;
 begin
   result:=UTF8Decode(trim(copy(A_Memo.Text,A_Memo.SelStart+1,A_Memo.SelLength)));
 end;
 
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon martin_frb » 7. Dez 2018, 01:06 Re: Memo Text-Markierung nicht erwünscht

Nicht getestet, aber nach der Beschreibung gehe ich davon aus, das NMemoTextDblClick aufgerufen wird, während die Maustaste unten ist (also bevor MouseUp).

ShowMessage setzt den Focus auf die MessageBox. Das Memo erhaelt die MouseUp message nicht, und bleibt in dem glauben die Maustaste sei gedrückt.

Moeglichkeiten....

1) Schreibe deinen Code ins MouseUp event.

2) CaptureControl := Memo (und dann im MouseUp CaptureControl := nil)
Allerdings, gibt das Probleme wenn auf einen anderem System DoubleClick nach MouseUp erfolgt, weil dann CaptureControl nicht geloescht wird.
Nicht sicher ob das Cross-Window geht....

----------------------
Das Verhalten kann man auch bei anderen nicht Lazarus apps provozieren.
martin_frb
 
Beiträge: 407
Registriert: 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other | 
CPU-Target: mostly 32 bit
Nach oben

Beitragvon Aliobaba » 7. Dez 2018, 09:14 Re: Memo Text-Markierung nicht erwünscht

Hallo und guten Morgen

Danke für Eure tolle Hilfe und für Eure Hilfsbereitschaft!!

@ Theo: " Memo.SelLength:=0; " hatte nichts gebracht; ich hab's im Vorfeld bereits ausprobiert.

@ wp_xyz: Mit den Tiefen der Vererbung habe ich mich - ehrlich gestanden - noch nie richtig vertraut gemacht. Deshalb verstehe ich den Satz " Man darf nie die Formular-Variable im Klassen-Code verwenden, denn dann funktioniert die Methode nur, wenn es dieses Formular mit exakt diesem Namen auch gibt" auch nicht wirklich vollständig und ganz. Fehler traten dabei bei mir noch nie auf, da ja immer ein entsprechendes Formular existiert(e). Möglicherweise hängt auch dies damit zusammen: Ich habe z.B. eine Unit "ohne Formular" (heißt bei mir "unit Globl;") und alle Variablen, die ich darin in der Abteilung "var" generiere, sind im gesamten Programm und in in allen Formularen aufrufbar.
Wie gesagt: Dies funktioniert bei mir, ich bin zufrieden - und Ja: Ich sollte mich mit diesem Thema wohl intensiver beschäftigen.

@ braunbär: Dieser Code funktioniert bei mir nicht. In "Showmessage" wird nichts angezeigt. Auch wenn ich vorher einen Text mit der Maus markiere, dann erscheint keine Ausgabe in "Showmessage". Der String "sss" bleibt wohl leer.

@martin_frb: Ich denke, Dein Hinweis und Deine Erklärung bzgl. des Ablaufs der einzelnen Maus-Events treffen den Nagel genau auf den Kopf: Wenn ich KEIN Showmessage aufrufe, sondern die "sss-Variable" z.B. unmittelbar in ein Textfeld schreiben lasse, dann läuft der Code prima und genau nach meinen Wünschen!! Auch mit Doppelklick, weil ja ein Maus-up Ereignis, das den gesamten Vorgang abschließt, innerhalb der Memo auftritt. [Jedenfalls erkläre ich mir das so]
Wenn der Code im "MouseUp-Event" ausgelöst wird, funktioniert auch der obige Code MIT ShowMessage. Da ich aber den Doppelklick brauche, kann ich den Code im "Doppelklick-Event" lassen, wenn ich auf das unmittelbar folgende "ShowMessage" verzichte.

Nochmals herzlichen Dank und einen schönen Tag!!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )
Aliobaba
 
Beiträge: 349
Registriert: 1. Mai 2012, 08:11

Beitragvon braunbär » 7. Dez 2018, 22:03 Re: Memo Text-Markierung nicht erwünscht

Aliobaba hat geschrieben:@ braunbär: Dieser Code funktioniert bei mir nicht. In "Showmessage" wird nichts angezeigt. Auch wenn ich vorher einen Text mit der Maus markiere, dann erscheint keine Ausgabe in "Showmessage". Der String "sss" bleibt wohl leer.

Da ist mir nicht klar, was bei dir passiert.
Wenn du im Memofeld auf ein Wort doppelklickst- ist denn dann nicht dieses Wort markiert?
Wenn das Wort markiert ist, dann ist selstart die Position des ersten Buchstaben (0-basiert, im String beginnt die Zählung aber bei 1, deshalb das +1) und sellength die Länge des markierten Bereichs. Ich kann mir schwer vorstellen, dass das bei dir nicht der Fall ist, da muss mMn ein anderer Fehler sein.

Übrigens, was vorher markiert oder nicht markiert war, ist egal. Per Doppeklick wird ein Wort markiert, und das Wort sollte dann im showmessage landen.
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon braunbär » 7. Dez 2018, 22:22 Re: Memo Text-Markierung nicht erwünscht

martin_frb hat geschrieben:Nicht getestet, aber nach der Beschreibung gehe ich davon aus, das NMemoTextDblClick aufgerufen wird, während die Maustaste unten ist (also bevor MouseUp).

ShowMessage setzt den Focus auf die MessageBox. Das Memo erhaelt die MouseUp message nicht, und bleibt in dem glauben die Maustaste sei gedrückt.

Moeglichkeiten....

1) Schreibe deinen Code ins MouseUp event.

2) CaptureControl := Memo (und dann im MouseUp CaptureControl := nil)
Allerdings, gibt das Probleme wenn auf einen anderem System DoubleClick nach MouseUp erfolgt, weil dann CaptureControl nicht geloescht wird.
Nicht sicher ob das Cross-Window geht....

----------------------
Das Verhalten kann man auch bei anderen nicht Lazarus apps provozieren.


Danke, offenbar ist das auch das Problem im Stringgrid mit Checkboxen. Die einfachste Lösung wird sein, in der CheckboxToggled Routine eine Mouseup Message ans Stringgrid zu schicken, das dürfte auch in keinem Fall schaden. In dieser Routine schreibe ich nämlich manchmal in andere visuelle Komponenten, und genau dann passiert das.
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon Aliobaba » 8. Dez 2018, 14:46 Re: Memo Text-Markierung nicht erwünscht

braunbär hat geschrieben:Da ist mir nicht klar, was bei dir passiert.
Wenn du im Memofeld auf ein Wort doppelklickst- ist denn dann nicht dieses Wort markiert?

Doch, Entschuldige, bitte! Ich habe die Meldung / den Befehl im Vorfeld abgefangen.
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )
Aliobaba
 
Beiträge: 349
Registriert: 1. Mai 2012, 08:11

Beitragvon braunbär » 8. Dez 2018, 20:33 Re: Memo Text-Markierung nicht erwünscht

Aliobaba hat geschrieben:@ wp_xyz: Mit den Tiefen der Vererbung habe ich mich - ehrlich gestanden - noch nie richtig vertraut gemacht. Deshalb verstehe ich den Satz " Man darf nie die Formular-Variable im Klassen-Code verwenden, denn dann funktioniert die Methode nur, wenn es dieses Formular mit exakt diesem Namen auch gibt" auch nicht wirklich vollständig und ganz. Fehler traten dabei bei mir noch nie auf, da ja immer ein entsprechendes Formular existiert(e). Möglicherweise hängt auch dies damit zusammen: Ich habe z.B. eine Unit "ohne Formular" (heißt bei mir "unit Globl;") und alle Variablen, die ich darin in der Abteilung "var" generiere, sind im gesamten Programm und in in allen Formularen aufrufbar.
Wie gesagt: Dies funktioniert bei mir, ich bin zufrieden - und Ja: Ich sollte mich mit diesem Thema wohl intensiver beschäftigen.

Das hat nichts mit Vererbung zu tun.
Methoden einer Klasse solten so geschrieben sein, dass sie für jedes Objekt funktionieren, das dieser Klasse angehört, egal, wie es heißt.
Die Klasse heißt TF_Text, die Methode heißt TF_Text.NMemoTextDblClick, und das Formular der Klasse, das automatisch generiert wird, heisst F_Text - man könnte aber auch andere Formulare dieser Klasse mit anderen Namen zur Laufzeit erzeugen.

Bei Formularen ist es eine verbreitete Unart, in den Methoden des Formulars für den Zugriff auf Properties des Formulars statt des Bezeichners self (den man im Methodenrumpf auch ganz weglassen kann) den Namen der Formvariablen zu verwenden, das ist aber eine eher unsaubere Programmierung - auch wenn es meistens funktionieren wird, weil es zur Laufzeit meistens nur ein Objekt der Klasse gibt, nämlich das in der LPR Datei automatisch erzeugte Formular.
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon braunbär » 8. Dez 2018, 22:21 Re: Memo Text-Markierung nicht erwünscht

Ich habe es jetzt in meinem Stringgrid ausprobiert, wo ich das gleiche Problem hatte wie du hier gepostet hast: ein sendmessage ist die einfachste Methode, das zu lösen.

Dazu musst du die Units LCLIntf (für Sendmessage) und LMessages (für die Konstantendeklaration LM_LBUTTONUP) in die uses Klausel von deinem Programm einbinden, und gleich als ersten Befehl von TF_Text.NMemoTextDblClick den Sendmessage Befehl einfügen:

Code: Alles auswählen
 
procedure TF_Text.NMemoTextDblClick(Sender: TObject);
 var
   sss : string;
 begin
    sendmessage(TMemo(Sender).Handle,LM_LBUTTONUP,0,0);
    sss := Wort_extrahieren ( NMemoText) ;    // Den 2. Parameter brauchst du nicht, weil du ja ohnehin NMemoText übergibst
    Showmessage (sss);
 end;
 


Damit weiß das Memofeld, dass die Maus-Taste losgelassen wurde und es wird nichts mehr markiert, wenn die Maus darüber bewegt wird. Schimmstenfalls bekommt das Memofeld die Message zweimal, aber das schadet nicht.
braunbär
 
Beiträge: 254
Registriert: 8. Jun 2017, 17:21

Beitragvon Aliobaba » 9. Dez 2018, 11:44 Re: Memo Text-Markierung nicht erwünscht

Danke "braunbär"!

Ich habe mich jetzt um das Problem "herumgemogelt", indem ich den Befehl beim "Mouse-up-Ereignis" nur ausführen lasse, wenn gleichzeitig die "Ctrl"-Taste gedrückt wird. Damit bleiben mir gleichzeitig alle Befehle verfügbar, die mit einem "normalen" MouseUp verbunden sein könnten.

Code: Alles auswählen
procedure TF_Text.NMemoTextMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  MeineVariable : string;
begin
  If (ssCtrl in Shift) then
  begin
         MeineVariable := Wort_extrahieren ( NMemoText , NMemoText.SelStart ) ;   
         exit;
  end;
end;

Deine Lösung werde ich aber auf jeden Fall noch ausprobieren. "sendmessage" funktioniert unter Linux und Windows gleichermaßen?
Schönen Sonntag!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )
Aliobaba
 
Beiträge: 349
Registriert: 1. Mai 2012, 08:11

Beitragvon Aliobaba » 9. Dez 2018, 11:47 Re: Memo Text-Markierung nicht erwünscht

... "MeineVariable" ist natürlich global, da ja sonst außerhalb der Prozedur nicht mehr verfügbar.

Code: Alles auswählen
procedure TF_Text.NMemoTextMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  If (ssCtrl in Shift) then
  begin
         MeineVariable := Wort_extrahieren ( NMemoText , NMemoText.SelStart ) ;   
         exit;
  end;
end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )
Aliobaba
 
Beiträge: 349
Registriert: 1. Mai 2012, 08:11

• Themenende •

Zurück zu Einsteigerfragen



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried