Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Text aus RTF mit formatierung übertragen


Eddie - Fr 04.11.05 16:59
Titel: Text aus RTF mit formatierung übertragen
Hi

ich habe zwei Richedits auf einer Form und in beiden steht etwas drin. Jetzt möchte ich den Text aus dem zweiten Richedit mit formatierung an das erste Richedit anhängen ohne dass der Text des ersten verloren geht und beide Texte untereinander stehen.

Bei meiner suche hier im Forum hab ich folgendes gefunden:
- http://www.delphi-forum.de/viewtopic.php?t=47411&start=0&postdays=0&postorder=asc&highlight=richedit
- http://www.delphi-forum.de/viewtopic.php?t=49528&start=0&postdays=0&postorder=asc&highlight=%2Astream

Bei beiden Methoden wird aber der Text des ersten Richedits überschrieben.
Wie kann ich aber den Text nur anhängen?


Lannes - Fr 04.11.05 19:38

Hallo,

wenn das nur ab Windows 2000 bzw. XP funktionieren muss,
dann hast Du mit dem Link schon die halbe Miete.
- http://www.delphi-forum.de/viewtopic.php?t=49528&start=0&postdays=0&postorder=asc&highlight=%2Astream

Du brauchst die dort enthaltene Funktion GetRTFFromRichEdit und folgenden Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var s : String;
begin
  RichEdit1.Lines.LoadFromFile('c:\@archiv\Tabelle.rtf');
  RichEdit2.Lines.LoadFromFile('c:\@archiv\Tabfarbe.rtf');
  s := GetRTFFromRichEdit(RichEdit2);
  RichEdit1.SelStart := Length(RichEdit1.Text);
  RichEdit1.SelText := s;


Sollte das nicht funktionieren, es gibt noch andere Möglichkeiten :wink:


alzaimar - Fr 04.11.05 20:13

Wenn man mit einem Stream die Lines-Eigenschaft des RichEdit Controls ausliest/beschreibt bekommt man die Formatierungen. Zweckmäßigerweise geht das mit einem TStringstream:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
Var
  s : TStringStream;

Begin
  s := TStringStream.create;
  Try
    MyRichEdit.Lines.SaveToStream (s);
    ShowMessage('Rich Text formatted stuff:'+s.DataString);
  Finally
    S.Free;
  End;
End;


Rolf_Geisler - Fr 04.11.05 21:48

Habe da noch eine einfachere Möglichkeit gefunden: Das Clipboard.


Quelltext
1:
2:
3:
    RichEdit1.SelectAll;
    RichEdit1.CopyToClipBoard;
    RichEdit2.PasteFromClipBoard;


hängt den Inhalt von RichEdit1 samt Formatierung an den Inhalt von RichEdit2 an. Funktioniert jedenfalls in D7. Mit Streams habe ich eine Weile erfolglos rumexperimentiert. Konnte zwar die beiden Felder zu einem gemeinsamen Text zusammenfassen, einschließlich Formatierung, aber nach RichEdit2.Lines.LoadFromStream(Stream) war das Zielfeld leer :-(.

MfG Rolf


Eddie - Fr 04.11.05 22:56

Vielen Dank für die Antworten. Das mit den Streams hat bei mir auf anhieb funktioniert.

Eine Frage hätte ich da noch: Funktioniert das mit den Streams wirklich nur ab Win2000/XP? Wenn ja, gibt es noch eine andere Lösung, außer das mit dem Clipboard? Ich hab so eine Sperre einprogrammiert, dass nichts aus der Zweischenablage in das Programm kopiert werden kann.


Lannes - Sa 05.11.05 01:40

Hallo,

@user profile iconalzaimar
das entspricht genau der Funktion GetRTFFromRichEdit (Direkt-Link) [http://www.delphi-forum.de/viewtopic.php?p=298933#298933]

user profile iconRolf_Geisler hat folgendes geschrieben:
Habe da noch eine einfachere Möglichkeit gefunden: Das Clipboard.

Würde mich -als Anwender- bedanken, wenn ein Programm meine Inhalte in der Zwischenablage überschreibt.
user profile iconRolf_Geisler hat folgendes geschrieben:
aber nach RichEdit2.Lines.LoadFromStream(Stream) war das Zielfeld leer :-(.

Vermute das Du die Stream-Position nicht richtig gesetzt hast:

Delphi-Quelltext
1:
2:
3:
   Stream.Seek(soFromBeginning,0);//<-------
   RichEdit2.PlainText := False;
   RichEdit2.Lines.LoadFromStream(Stream);


user profile iconEddie hat folgendes geschrieben:
Eine Frage hätte ich da noch: Funktioniert das mit den Streams wirklich nur ab Win2000/XP? Wenn ja, gibt es noch eine andere Lösung, außer das mit dem Clipboard? Ich hab so eine Sperre einprogrammiert, dass nichts aus der Zweischenablage in das Programm kopiert werden kann.
Streams haben bzgl. älteren Betriebssystemen, soweit ich weis, keine Einschränkungen.
Das Problem liegt in der Zeile begraben:

Delphi-Quelltext
1:
RichEdit1.SelText := s;                    
Dort wird an Seltext der aus RichEdit per Stream geladene Rtf-Code zugewiesen.
Die Interpretation des Rtf-Codes wird durch die dem Betriebssystem zugehörige riched32.dll ausgeführt und dann in den Rtf-Code des Ziel-Richedits integriert.
Die ältere riched32.dll z.B. bei NT kann das nicht, der RTF-Code wird nicht interpretiert, sondern als Plaintext angezeigt:

Quelltext
1:
{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang103                    

Deshalb vermute ich das ein Umweg über das Clipboard auch nur ab Win2000/XP funktioniert(muss ich mal testen).

Eine Lösung die auch unter z.B. NT funktioniert hat user profile iconFlocke in der Delphi-Praxis vorgestellt:
function _AddRtfCallback [http://www.delphipraxis.net/post385793.html#385793]


Eddie - Sa 05.11.05 20:14

user profile iconLannes hat folgendes geschrieben:
Eine Lösung die auch unter z.B. NT funktioniert hat user profile iconFlocke in der Delphi-Praxis vorgestellt: function _AddRtfCallback [http://www.delphipraxis.net/post385793.html#385793]

Das hab ich mal ausprobiert. Es hat irgendeine Fehlermeldung in Delphi aufgebracht. (Da würd ich mich aber jetzt nicht ganz nach richten. Ich bekomme unter Windows und Delphi in letzter Zeit öfter mal Fehlermeldungen) :wink:

Aber auf der Seite schreibt "meierotto", dass er mit dem Jedi-RichEdit arbeitet. Ist das bei den Jedi-VCL Komponenten dabei? Würde das nicht unabhängig von der Win-Version funktionieren?


Rolf_Geisler - So 06.11.05 15:12

Hi,
ich muss noch mal auf Lannes' Kommentar vom 5.11. 00:40 zurückkommen. Something seems to go wrong ...

1. OK, die Position im Stream war nicht gesetzt ...
2. ... aber auch nach Stream.Seek(..) habe ich nicht, was Eddie will.

Variante 1
Wenn ich einfach RichEdit1.Lines auf den Stream sichere und von RichEdit2.Lines einlesen lasse, vergißt RichEdit2 seinen gesamten bisherigen Inhalt und ersetzt ihn durch den Stream, also RichEdit1. Sagt auch die online-Hilfe. Oder gibt's da noch was Besonderes?

Variante 2
Wenn ich die beiden RichEdits auf dem Stream zusammenfasse und dann als Paket von RichEdit2 einlesen lasse, klappts auch nicht. Im Stream stehen nämlich nach dem zweifachen SaveToStream zwei komplette RTF-Pakete. Nach dem Einlesen steht in RichEdit2 nur das zweite RTF-Paket aus dem Stream.
Wie das bei mir aussieht, habe ich als Dateianhang angehängt. Vielleicht hat jemand eine Idee ...

Nur bei CopyToClipboard / PasteFromClipboard hat RichEdit2 den Inhalt von RichEdit1 an RichEdit2 korrekt angehängt. Also, gibt's da noch was Spezielles für Streams im Zusammenhang mit RTF-Text?

Mfg Rolf


Lannes - So 06.11.05 21:59

Hallo,

zu Variante 1:
Das ist klar, LoadFromStream(Stream), ersetzt den Inhalt des RichEdit.
Dazu gibt es nichts Besonderes zu sagen.

zu Variante 2:
Ich weis nicht wie Du die Streams zusammensetzt, mir ist aufgefallen das zweimal das gleiche vorhanden ist.
Hier der betreffende Auszug aus Deinem Anhang:

Quelltext
1:
2:
3:
4:
5:
6:
{\rtf1\ansi\ansicpg1252\deff0\deflang1031
{\fonttbl{\f0\fnil MS Sans Serif;}}
\viewkind4\uc1\pard\f0\fs20 RichEdit1\par \par }
{\rtf1\ansi\ansicpg1252\deff0\deflang1031
{\fonttbl{\f0\fnil MS Sans Serif;}}
\viewkind4\uc1\pard\f0\fs20 RichEdit1\par \par }
user profile iconRolf_Geisler hat folgendes geschrieben:
Nach dem Einlesen steht in RichEdit2 nur das zweite RTF-Paket aus dem Stream.
Bist Du sicher das es das zweite Paket aus dem Stream ist?

Der RTF-Reader beachtet die geschweiften Klammern, wenn alle geschlossen sind, wird nicht weiter interpretiert.
Hab sie farblich markiert, damit es deutlich wird.

Aus diesem Grund ist es nicht möglich die Inhalte zweier Richedits incl. der Formatierungen aneinanderzuhängen.

Mit PasteFromClipboard fügst Du den Inhalt der Zwischenablage an der Cursorposition ein,
und er wird interpretiert.
Das ist gleichzusetzen mit:

Delphi-Quelltext
1:
2:
3:
4:
s := '{\rtf1\ansi\ansicpg1252\deff0\deflang1031' 
     +'{\fonttbl{\f0\fnil MS Sans Serif;}}' 
     +'\viewkind4\uc1\pard\f0\fs20 Dieser Text ist neu hinzugekommen\par \par }';
RichEdit1.SelText := s;


Hast Du den Code getestet der bei user profile iconEddie funktioniert hat?
Ich hab in nochmal zusammengefasst:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure RichEditAddRichEdit(ZielRE,QuelleRE: TRichEdit);
var StrS : TStringStream;
    s : String;
begin
  StrS := TStringStream.Create('');
  try
    QuelleRE.Lines.SaveToStream(StrS);
    s := StrS.DataString;
    ZielRE.SelStart := Length(ZielRE.Text);
    ZielRE.SelText := s;
  finally
    StrS.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  //der Inhalt von RichEdit2 -incl. der Formatierungen-
  //wird an RichEdit1 angehängt
  RichEditAddRichEdit(RichEdit1,RichEdit2);
end;


:!: Der Code funktioniert erst ab win2000/XP :!:


Rolf_Geisler - Sa 12.11.05 19:48

Hi,

danke. Jetzt ist alles klar. Wenn ich Dein Code-Beispiel vom 4.11. gleich richtig gelesen hätte, hätte ich nicht so ewig herumexperimentieren müssen. SaveToStream ist logischerweise der Weg in den Stream hinein, aber heraus führt nicht LoadFromStream, sondern der DataString.

Vielen Dank noch mal für die Klarstellung. Gruß Rolf