| Autor |
Beitrag |
galagher
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 28.05.07 10:54
Hallo!
Ich wende mich mal wieder hoffnungsvoll ans Delphi-Forum! Ich möchte, dass in einem RichEdit automatisch die Zeilenumbruch-Zeichen #13#10 eingefügt werden, wenn die Zeile RichEdit1.ClientWidth - sprich, den rechten Rand - erreicht. WordWrap tut zwar genau das, aber es fügt mir kein #13#10 ein.
Wie kann man feststellen, ob die Zeile, in der gerade getippt wird, "pixelmässig" den rechten Rand erreicht? Hab's schon mit .CaretPos.X versucht, aber das gibt nicht den Pixelwert zurück. Erschwerdend kommt noch hinzu, dass in der Zeile unterschiedliche Schriftarten und -grössen usw. verwendet werden können.
Wie kann man das machen?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bernhard Geyer
      
Beiträge: 721
Erhaltene Danke: 3
|
Verfasst: Mo 28.05.07 11:49
Deine Probleme zeigen dir ja das die Standardlösung von RichEdit viel besser ist da sie unabhängig von Schriftart und größe funktioniert.
Was für einen Vorteil hast du wenn CRLF ergänzt wird?
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 28.05.07 13:08
Bernhard Geyer hat folgendes geschrieben: | Deine Probleme zeigen dir ja das die Standardlösung von RichEdit viel besser ist da sie unabhängig von Schriftart und größe funktioniert.
Was für einen Vorteil hast du wenn CRLF ergänzt wird? |
Ich brauche CRLF, weil ich einzelne Zeilen benötige, die ich auf unterstrichene Zeichen abfrage. Das funktioniert nicht, wenn WordWrap := True. Um nun am rechten Rand nicht die Eingabetaste drücken zu müssen, wäre es praktisch, wenn das CRLF automatisch eingefügt würde.
Man müsste halt dann noch herausfinden, an welcher Stelle das sinnvoll ist. Zunächst einmal muss ich irgendwie die Caret-Position in Pixel umrechnen und mit ClientWidth vergleichen, aber wie? Oder kann man WordWrap so modifizieren, dass es den Zeilenumbruch nicht nur darstellt, sondern das CRLF auch einfügt?
Leider gibt's in den Prozeduren KeyDown und KeyPress kein X Y - Variablen wie in zB. OnMouseMove.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bernhard Geyer
      
Beiträge: 721
Erhaltene Danke: 3
|
Verfasst: Di 29.05.07 06:28
Würde auch ein HTML-Control gehen? Da HTML ja Hyperlinks gehen würde die Benachrichtigung über einen Click auf einen Link-Text das Control bestimmen.
|
|
chrisw
      
Beiträge: 439
Erhaltene Danke: 3
W2K
D7
|
Verfasst: Di 29.05.07 07:03
Grundsätzlich würde ich für die Abfrage nach unterstrichenen Zeichen die Strings aus Lines nutzen, aber wenn du unbedingt
CRLF brauchst, dann füg es doch ein:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var i : Integer; s : String; begin for i := 0 to RichEdit1.Lines.Count -1 do s := s + RichEdit1.Lines[i] + #13#10; showmessage(s); end; |
Oder hab ich was falsch verstanden ?
CU
Chris
_________________ Man sollte keine Dummheit zweimal begehen, die Auswahl ist schließlich groß genug.
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 29.05.07 17:13
Bernhard Geyer hat folgendes geschrieben: | | Würde auch ein HTML-Control gehen? Da HTML ja Hyperlinks gehen würde die Benachrichtigung über einen Click auf einen Link-Text das Control bestimmen. |
Verstehe nicht, was du meinst! Kenne mich mit HTML absolut nicht aus, und was im RichEdit als Hyperlink gilt, ist einfach nur unterstrichener Text, den man anklicken kann wie ein "richtiges" Hyperlink!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 29.05.07 17:30
chrisw hat folgendes geschrieben: | | Grundsätzlich würde ich für die Abfrage nach unterstrichenen Zeichen die Strings aus Lines nutzen |
Das tue ich im Moment ja, aber es funktioniert nur mit "richtigen" Lines, also bei solchen, die #13#10 an ihrem Ende haben. Ich poste mal den Code, der das macht - vielleicht kann man ihn so modifizieren, dass er auch dann korrekt ist, wenn WordWrap := True (wenn also unter Umständen überhaupt keine CRLF's vorkommen). Der Code kann bei eingeschaltetem WordWrap nur unterstrichene Zeichen in der 1. dargestellten Zeile korrekt verarbeiten, bei den anderen Zeilen funktioniert er nicht oder nicht korrekt.
Hier also:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58:
| function ScanString(RichEdit: TRichEdit; X, Y: Integer): String; var iCharIndex, iLineIndex, iCharOffset, lc, n, c, t: Integer; Pt: TPoint; begin with RichEdit do begin RichEdit.Cursor := crArrow;
Pt := Point(X, Y+2);
iCharIndex := Perform(Messages.EM_CHARFROMPOS, 0, Integer(@Pt)); if iCharIndex < 0 then Exit;
iLineIndex := Perform(EM_EXLINEFROMCHAR, 0, iCharIndex); iCharOffset := iCharIndex - Perform(EM_LINEINDEX, iLineIndex, 0);
if (Lines.Count - 1 < iLineIndex) or (Length(Lines[iLineIndex]) = 0) then exit;
Result := '';
lc := 0; for n := 0 to iLineIndex-1 do lc := lc+Length(Lines[n])+2;
t := SelStart;
for c := iCharOffset downto 1 do begin SelStart := lc+c; if not (fsUnderLine in SelAttributes.Style) then break; end;
for n := c+1 to Length(Lines[iLineIndex]) do begin SelStart := lc+n; if fsUnderLine in SelAttributes.Style then begin Result := Result+Lines[iLineIndex][n]; RichEdit.Cursor := crHandPoint; end else break; end;
SelStart := t;
if Y >= iLineIndex then SelStart := iCharIndex;
if not (fsUnderLine in SelAttributes.Style) or (iCharOffset = Length(Lines[iLineIndex])) then RichEdit.Cursor := crArrow; end; end; |
In Prozedur RichEdit1MouseMove erfolgt der Aufruf der Funktion.
Ich muss anmerken, dass ich den Originalcode aus dem Internet her habe (von den Schweizern?), ich aber damals noch nicht vermerkt habe, wer der Autor ist und woher ich den Code habe. Jetzt mache ich das immer. Ich habe den Code so angepasst, dass er nicht mehr das Wort oder die Zeile zurückgibt, auf dem der Cursor liegt, sondern nur unterstrichenen Text. Aber wie gesagt, es funktioniert nur mit WordWrap := False
chrisw hat folgendes geschrieben: | | for i := 0 to RichEdit1.Lines.Count -1 do s := s + RichEdit1.Lines[i] + #13#10; |
Ich meinte, schon während des Tippens soll CRLF eingefügt werden. Aber eleganter wäre es, obigen Code "WordWrap"-tauglich zu machen, bloss weiss ich nicht, wie!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Di 29.05.07 20:04
Hallo,
lass doch den umständlichen Zugriff über Lines[x] weg, CharIndex und RichEdit.Text ist schon ausreichend für eine solche Funktion. Damit wäre dein Problem dann auch gelöst.
Hab Deinen Code mal umgestellt, eventuell musst Du noch ein paar Feinheiten einbauen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| function ScanStringII(RichEdit: TRichEdit; X, Y: Integer): String; var Pt: TPoint; iCharIndex, iLength, iStart, i : Integer; begin Result := ''; Pt := Point(X, Y+2); with RichEdit do begin iCharIndex := Perform(Messages.EM_CHARFROMPOS, 0, Integer(@Pt)); SelStart := iCharIndex; if fsUnderLine in SelAttributes.Style then begin Cursor := crHandPoint;
i := iCharIndex; while (i > 0) and (fsUnderLine in SelAttributes.Style) do begin dec(i); SelStart := i; end; iStart := i+1;
i := iCharIndex; SelStart := i; iLength := Length(Text); while (i < iLength) and (fsUnderLine in SelAttributes.Style) do begin inc(i); SelStart := i; end;
Result := Copy(Text,iStart,i-iStart); SelStart := iCharIndex; end else Cursor := crArrow; end; end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 30.05.07 17:22
Lannes hat folgendes geschrieben: | | lass doch den umständlichen Zugriff über Lines[x] weg, CharIndex und RichEdit.Text ist schon ausreichend für eine solche Funktion. Damit wäre dein Problem dann auch gelöst. |
Ja, genau! Passt alles, funktioniert, man muss nur noch beim Ermitteln von Wortbeginn und -ende darauf achten, dass man keine #13 und #10 mit aufnimmt, die vorkommen können:
Delphi-Quelltext 1:
| if (Text[i] = #13) or (Text[i] = #10) then break; |
Danke! Bis jetzt hat dein Code alle Test bestanden!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 09.06.07 09:26
Hallo!
Funktioniert alles bestens, nur wie stoppe ich das Scrollen des Richedits? Das Caret folgt ja dem Mauscursor, das soll und muss auch so sein. Wenn der Text länger ist als das RichEdit anzeigen kann, gibt's eine VScrollbar und das RichEdit scrollt weiter, wenn die Maus bewegt wird. Das ist irgendwie störend, wie kann man das verhindern?
Habe schon experimentiert, CaretPos.Y mit der letzen angezeigten Zeile zu vergleichen, komme aber so nicht weiter, das klappt nicht. Wie gesagt, das Caret muss dem Cursor folgen, aber ohne dabei zu scrollen, das soll man selbst tun müssen. Dann folgt das Caret wieder dem Cursor, stoppt, bevor das RichEdit scrollt, ... usw.
Geht das überhaupt?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Sa 09.06.07 11:31
Hallo,
das mit dem Scrollen kann ich nicht nachvollziehen.
Hab es gerade noch mal mit meinem Code getestet. Wie sieht Dein Code denn jetzt aus?
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 09.06.07 13:31
Lannes hat folgendes geschrieben: | Hallo,
das mit dem Scrollen kann ich nicht nachvollziehen.
Hab es gerade noch mal mit meinem Code getestet. Wie sieht Dein Code denn jetzt aus? |
Naja, so:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
|
function ScanString(RichEdit: TRichEdit; X, Y: Integer): String; var Pt: TPoint; n, iCharIndex, iLength, iStart, i : Integer; begin Result := ''; Pt := Point(X, Y+2);
with RichEdit do begin iCharIndex := Perform(Messages.EM_CHARFROMPOS, 0, Integer(@Pt)); Cursor := crArrow;
SelStart := iCharIndex;
if fsUnderLine in SelAttributes.Style then if iCharIndex < Length(Text) then begin i := iCharIndex+1; while (i > 0) and (fsUnderLine in SelAttributes.Style) do begin if (Text[i] = #13) or (Text[i] = #10) then break; dec(i); SelStart := i; end; iStart := i+1;
n := i;
i := iCharIndex; SelStart := i;
iLength := Length(Text)+1; while (i < iLength) and (fsUnderLine in SelAttributes.Style) do begin if (Text[i] = #13) or (Text[i] = #10) then break; inc(i); SelStart := i; end;
Result := Copy(Text,iStart,i-iStart);
if Result <> '' then Cursor := crHandPoint else Cursor := crArrow;
SelStart := iCharIndex; end else Cursor := crArrow; end; end; |
Und so erfolgt der Aufruf:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if TRichEdit(Sender).SelLength = 0 then if not (ssLeft in Shift) then LinkStr := ScanString(TRichEdit(Sender), X, Y); end; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 10.06.07 18:24
Hab's jetzt endlich geschafft, RXRichEdit zu installieren:
sourceforge.net/proj...tup.exe&27199407
Läuft auch, klappt alles. Aber jetzt kann er mit der ScanString-Funktion von Lannes nicht: Es wird manchmal nicht der korrekte unterstrichene String zurückgegeben, wobei der Fehler nie in der 1. Zeile auftritt.
Bei zB.
ABC
DEF
GHI
erkent er ABC korrekt, DEF nur, wenn der Mauszeiger zwischen dem D und dem E ist, und GHI wird gar nicht erkannt. Werden Leerzeilen dazwischen eingefügt, verschiebt sich wieder alles und es klappt wieder nicht richtig. Ich vermute, dass das an
Delphi-Quelltext 1:
| iCharIndex := Perform(Messages.EM_CHARFROMPOS, 0, Integer(@Pt)); |
liegt.
Es klappt weder mir dem Original-Code von Lannes noch mit meinem veränderten - Result ist nicht korrekt. Wie bekomme ich das denn nun in den Griff? Endlich habe ich ein grafikfähiges RichEdit, und dann das!
Ist jemand dabei, der hier weiter weiss?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 10.06.07 19:52
iCharIndex ermittelt also das so und sovielte Zeichen im Text.
Bei RxRichEdit wird CRLF als 1, bei RichEdit als 2 Zeichen gezählt. Bei der ersten Zeile werden bei beiden zB. korrekt 20 Zeichen angegeben, nur ist bei RichEdit der Anfang der 2. Zeile iCharIndex = 22, bei RxRichEdit 21. So kommt man nie hin. Wie behebe ich das am Besten?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: So 10.06.07 20:31
Hallo,
ich kenne das RxRichEdit nicht, aber könnte es sich einmal um echte Zeilenumbrüche handeln und das andere mal durch WordWrap erzeugte Umbrüche?
Beim Standard-Richedit werden durch WordWrap erzeugte Umbrüche nur durch #10 realisiert, nicht mit #13#10.
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 10.06.07 20:47
Lannes hat folgendes geschrieben: | | ich kenne das RxRichEdit nicht, aber könnte es sich einmal um echte Zeilenumbrüche handeln und das andere mal durch WordWrap erzeugte Umbrüche? |
Bei WordWrap-erzeugten Umbrüchen klappt ja alles, nur bei CRLF nicht! Wenn man den Text kopiert und als .txt.Datei speichert, zeigt der HexEditor 0D0A an - es gibt also echte CRLF's bei RxRichEdit. Aber irgendwie wird der "echte" Zeilenumbruch nur mit 1 Zeichen gerechnet. Auch SelStart := iCharIndex funktioniert korrekt.
Anfang und Ende des unterstrichenen Textes können nicht korrekt gefunden werden, sodass Result einen anderen String enthält als der unterstrichene Text ist. Bei WordWrap ist es egal, über wieviele "Zeilen" ein unterstrichener Text geht, da funktioniert alles. Aber wehe, es ist irgendwo oberhalb des unterstrichenen Textes ein echtes CRLF - schon stimmt nichts mehr, und zwar um 1 Zeichen pro CRLF.
Ich weiss nicht, wie ich das in den Griff bekommen soll!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mo 11.06.07 08:06
Hallo,
Du schreibst das "SelStart := iCharIndex" korrekt funktioniert.
Versuch doch mal die Funktion komplett auf die Selection umzustellen, die Zuweisung an Result könnte man z.B. über Auswerten von SelText realisieren.
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 11.06.07 16:31
Lannes hat folgendes geschrieben: | | Du schreibst das "SelStart := iCharIndex" korrekt funktioniert. |
Ja, das Caret folgt über alle Zeilen korrekt dem Mauszeiger!
Lannes hat folgendes geschrieben: | | Versuch doch mal die Funktion komplett auf die Selection umzustellen |
Wie meinst du das? Wie umstellen?
//Edit:
Ein Test mit Caption := Text[SelStart] ergab, dass nicht das Zeichen bei SelStart ausgegeben wird, sondern abhängig von den CRLF's ein Zeichen an einer anderen Position. Irgendwas stimmt mit RxRichEdit.Text nicht!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mo 11.06.07 18:18
Hallo,
würde eher sagen etwas ist anders.
Auf Selection umstellen:
Halt nicht auf RichEdit.Text zugreifen, sondern bei Bedarf die Selection mit SelLength setzen und dann RichEdit.SelText auswerten.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| SelLength := 1; if SelLength = 0 then break; SelLength := SelStart-i-iStart; Result := SelText; |
Ob das funktioniert im RXRichEdit, kA, mit dem Standard-RichEdit funktioniert es.
Ein Versuch ist es auf jeden Fall wert 
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
galagher 
      
Beiträge: 2562
Erhaltene Danke: 46
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 11.06.07 18:41
Lannes hat folgendes geschrieben: | | Ob das funktioniert im RXRichEdit, kA, mit dem Standard-RichEdit funktioniert es. |
Nein, klappt nicht. Der Text flackert wie wild durch das Hin und Her des Carets und es wird nur das letzte unterstrichene Wort ermitelt, egal in welcher Zeile.
Aber es gibt unter anderem folgende Eigenschaften und Funktionen bei RxRichedit:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| GetSelection GetLineIndex(LineNo: Integer) GetCharPos(CharIndex: Integer) GetLineLength(CharIndex: Integer) GetTextLen: Integer GetCaretPos: TPoint LineFromChar(CharIndex: Integer) |
Habe es auch schon damit versucht, aber ohne Erfolg...
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
|