Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - RichEdit und Hyperlinks


LonghornUser - So 30.05.10 22:25
Titel: RichEdit und Hyperlinks
Liebe Gemeinde :),

ich habe vor, einen kleinen Editor in ein bestehendes Programm einzubauen, was bis jetzt auch super funktioniert hat. Nur ein kleines Problem gibt es: es werden keine Hyperlinks von TRichEdit unterstützt.

Wenn ich einen Link aus einem anderen Programm in mein RichEdit einfüge, kommt dann in etwa das heraus:
Link <http://www.domain.de>;

Aber ein Link ist das dann nicht mehr, lediglich ein formatierter blauer, unterstrichener Text.

Wie ich aber durch Recherche herausgefunden habe, unterstützt das RichText-Format durchaus Hyperlinks:
Zitat:

{\field{\*\fldinst{HYPERLINK "http://www.domain.de"}}{\fldrslt{\ul\cf2 Link}}}


Wieso wird das nicht vom TRichEdit unterstützt?

Ich habe mir nun einen kleinen Workaround überlegt, der wie folgt aussieht:
Für Hyperlinks führe ich in meinem RichEdit eine eigene Syntax ein, bspw. <!Address=...|Name=...!>, die dann in der gespeicherten RTF-Datei wieder durch o.g. RTF-Syntax ersetzt wird.

Das wäre allerdings eine äußerst unschöne Lösung :(

Habt ihr da vielleicht einen anderen Vorschlag?

Ciao LHUser


Xion - So 30.05.10 23:32

guck mal da
http://delphi.about.com/od/vclusing/l/aa111803a.htm


Lannes - So 30.05.10 23:47

Hallo,

schau dir doch mal das an, incl. speichern:
Delphi-Praxis: TRichedit - Speichern inkl. Links [http://www.delphipraxis.net/topic134864,0,asc,0.html]
Nachteil ist das nur dein Programm eine solche gespeicherte Datei wieder richtig anzeigen kann.


LonghornUser - Mi 02.06.10 23:18

Das würde mir schon reichen.

Ich habe den Code mal eingegeben, aber leider sagt mir der Compiler "@CF2Set" kennt er nicht. Muss man hier noch irgendeine Unit einbinden?


Lannes - Do 03.06.10 00:29

Hallo,

in dem beispielhaften Aufruf(am Ende des Tipps) findest du die benötigten Variablendeklaration und die zugehörige Initialisierung. Ich würde die Variablen aber nur einmalig beim Start der Anwendung initialisieren.


LonghornUser - Do 03.06.10 21:49

OK, ich habe den Code jetzt mal ausprobiert und er hat anscheinend keine Wirkung.

Ich schreibe mal lieber, was ich mit dem Inhalt des RichEdits machen will. Ich will, dass Hyperlinks so im RichEdit angezeigt werden, dass, wenn ich den kompletten Inhalt in die Zwischenablage kopiere, der Link nach dem Einfügen in irgendein anderes Programm, welches Links unterstützt (etwa Word oder ein E-Mail-Programm), immernoch da ist.

Von daher ist auch der Code von http://delphi.about.com/od/vclusing/l/aa111803a.htm nicht hilfreich, denn, wenn ich den Inhalt des RichEdits in ein anderes Programm kopiere, ist der Link wieder ein normaler Text.


Gerd Kayser - Fr 04.06.10 04:51

Versuchs mal damit:

http://www.swissdelphicenter.ch/en/showcode.php?id=1652

Zwei Dinge sind zu beachten:

1. Die Variable mask muß vom Typ Integer sein, nicht Word (Fehler im Sourcecode).
2. RichEdit muß direkt auf dem Formular liegen, sonst kommen die Messages beim Anklicken nicht an.


LonghornUser - Fr 04.06.10 12:53

Das ist ein Code, der ähnlich zu dem aus dem 2. Post ist (http://delphi.about.com/od/vclusing/l/aa111803a.htm). Auch hier ist das Problem, dass die Links zwar korrekt dargestellt werden, aber wenn ich den Text etwa in Word kopiere, ist der Hyperlink wieder verschwunden (Was auch nicht verwunderlich, denn der Code *simuliert* nur, dass es ein Link wäre. Es ist aber weiterhin Text).

Moderiert von user profile iconNarses: URL-Tag hinzugefügt.


jaenicke - Fr 04.06.10 14:37

Die Frage ist in welcher Version das Rich Edit Control denn Links unterstützt, denn in Delphi wird noch das Rich Edit 1.1 Control oder so verwendet (ok, D2010 hab ich da noch nicht geprüft). Dementsprechend werden neuere Features (so es sich hier um eins handelt) natürlich nicht unterstützt.


LonghornUser - Fr 04.06.10 15:01

Ich habe Delphi 2010 und dort gehts wie gesagt auch nicht. Ich habe vorhin gesehen, dass im JvRichEdit z.B. Links schon funktionieren, aber sie werden halt auch nur simuliert. Ich möchte halt den RichText in die Zwischenablage bekommen.

Oder gibt es eine Möglichkeit, den Inhalt einer RTF-Datei, ohne sie in ein RichEdit zu laden, in die Zwischenablage zu bekommen?

Moderiert von user profile iconNarses: * in [b]-Tags gewandelt.


jaenicke - Fr 04.06.10 16:06

Dafür muss im Grunde nur der Text aus der Datei mit dem Typ RTF (keine Ahnung wie der konkrete Typ lautet) in die Zwischenablage nehme ich an. Da müsste ich mir mal meinen Clipboard Viewer anschauen, denn der kennt glaube ich den Typ und stellt den dar.


LonghornUser - Fr 04.06.10 16:25

Naja, nur der Text aus der RTF-Datei wird schwierig, denn das ist ja ein formatierter Text (mit Notation), sprich irgendeine Instanz muss ja die Notation wieder in formatierten Text interpretieren. Und das interpretierte Ergebnis (was normalerweise in einem RichEdit dargestellt würde, wenn es funktionieren würde... :)) soll dann in die Zwischenablage.


jaenicke - Fr 04.06.10 16:39

http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx
Du musst nur den Text reinkopieren mit dem Code C11E. Das ist das RTF Format. Dann gibt es noch C131 (RTF als normaler Text) und C133 (RTF ohne eingebettete Objekte). Im Grunde musst du aber überall nur den selben Text als Daten reinlegen.
Die Codes habe ich gerade im Viewer gesehen, so kopiert es jedenfalls Wordpad.


LonghornUser - Fr 04.06.10 16:56

Ich denke, so etwas ähnliches passiert in diesem Code, nur dass nicht das vordefinierte RTF-Format genutzt wird (was es wohl gar nicht gibt: "since this is not a predefined format", siehe hier [http://www.swissdelphicenter.ch/torry/showcode.php?id=1606]), sondern ein eigenes angelegt wird:

Delphi-Quelltext
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:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Clipbrd, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    CF_RTF: Word;
    procedure RTFtoClipboard(txt: string; rtf: AnsiString);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  RTFtoClipboard('Ausweichtext',Memo1.Text); // Der Ausweichtext wird eingefügt, wenn die Zielanwendung kein RTF versteht
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
CF_RTF := RegisterClipboardFormat('Rich Text Format');
  if CF_RTF = 0 then
    raise Exception.Create('Unable to register the Rich Text clipboard format!');
end;

procedure TForm1.RTFtoClipboard(txt: string; rtf: AnsiString);
var
  Data: Cardinal;
begin
  with Clipboard do
  begin
    Data := GlobalAlloc(GHND or GMEM_SHARE, Length(rtf)*SizeOf(AnsiChar) + 1);
    if Data <> 0 then
      try
        StrPCopy(GlobalLock(Data), rtf);
        GlobalUnlock(Data);
        Open;
        try
          AsText := txt;
          SetAsHandle(CF_RTF, Data);
        finally
          Close;
        end;
      except
        GlobalFree(Data);
        ShowMessage('Unable to copy the selected RTF text');
      end
    else
      ShowMessage('Global Alloc failed during Copy to Clipboard!');
  end;
end;

end.

Quelle: http://stackoverflow.com/questions/915168/how-to-copy-a-rtf-string-to-the-clipboard-in-delphi-2009

Das einzige, was hier blöd ist: Unicode fällt in Verbindung mit dem Ansi-RTF-Format wohl flach.


Martok - Fr 04.06.10 18:04

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Die Frage ist in welcher Version das Rich Edit Control denn Links unterstützt, denn in Delphi wird noch das Rich Edit 1.1 Control oder so verwendet (ok, D2010 hab ich da noch nicht geprüft).

TRichEdit ist tatsächlich 1.1, die ganzen interessanten Features, die RichText erst interessant machen, stammen fast alle aus RichText 2.0.

Dafür gab es schon vor 10 Jahren TRxRichEdit aus der RXLib, heute im Rahmen der JVCL zu bekommen. Bestimmt auch andere, aber das ist so das was ich überall verbaut hab.

user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
Das einzige, was hier blöd ist: Unicode fällt in Verbindung mit dem Ansi-RTF-Format wohl flach.

Möglicherweise existiert von dem Jedi-Edit da ein D2010-Unicode-Port?


Gerd Kayser - Fr 04.06.10 20:16

user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
Das ist ein Code, der ähnlich zu dem aus dem 2. Post ist (http://delphi.about.com/od/vclusing/l/aa111803a.htm). Auch hier ist das Problem, dass die Links zwar korrekt dargestellt werden, aber wenn ich den Text etwa in Word kopiere, ist der Hyperlink wieder verschwunden


Ich hab die von mir vorgeschlagene Variante vorhin ausgiebig getestet (BDS2006, Word 2007, Windows 7 32-Bit).

1. Ein einzelner Link in Word eingefügt, funktioniert.
2. Text mit Link in Word eingefügt, funktioniert nicht.

Daß der Text mit Links nicht korrekt in Word angezeigt wird, liegt weder am Clipboardformat noch am RichEdit von Delphi. Wird der Text mit den Links in Wordpad bzw. Write eingefügt, ist alles so, wie es sein soll. Kopiert man den Text inkl. Links aus Wordpad bzw. Write und fügt es in Word ein, so arbeitet auch Word wunschgemäß.

Meiner Meinung nach liegt das Problem eindeutig bei Word.


LonghornUser - Fr 04.06.10 21:02

Das Problem an deinem Code ist, dass kein wirklicher "Link" erzeugt wird, sondern nur eine "Link-Struktur" erkannt und dann farblich angepasst wird. Wenn ich das ganze in die Zwischenablage kopiere, ist und bleibt es nur ein (blau und unterstrichen) formatierter Text.

So zumindest verstehe ich den Code.

Ich werde das ganze übrigens nun so machen:
0. Ich führe eine eigene Syntax für Hyperlinks ein (siehe meine obigen Posts).
1. Text wird normal in einem JvRichEdit geschrieben und formatiert (URL Highlighting ist im JvRichEdit schon "ab Werk" drin).
2. Dann wird das ganze in eine RTF-Datei gespeichert und in dieser RTF-Datei wird die Hyperlink-Syntax durch die RTF-eigene Hyperlink-Notation ersetzt.
3. Diese veränderte RTF-Datei wird dann in die Zwischenablage kopiert und Voila :)

Eine ziemlich hässliche Lösung, aber leider habe ich keine andere Idee.


Lannes - Do 10.06.10 19:36

Hallo,

user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
2. Dann wird das ganze in eine RTF-Datei gespeichert und in dieser RTF-Datei wird die Hyperlink-Syntax durch die RTF-eigene Hyperlink-Notation ersetzt.
3. Diese veränderte RTF-Datei wird dann in die Zwischenablage kopiert und Voila :)

Damit könntest Du Dir vermutlich die Krücke mit der Datei sparen:
[TRichEdit, VCL Win32] Formatierten RichEdit-Text per String übertragen [http://www.delphi-forum.de/viewtopic.php?t=55781&start=0&postorder=asc]


LonghornUser - Do 10.06.10 22:06

Nee, das ganze funktioniert leider nicht, da mit SaveToStream nur der Text, nicht aber der RTF-Quelltext gespeichert wird.

Mit folgendem Quelltext wird von showMessage leider nur der Text ausgegeben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  stream := TMemoryStream.Create;
  stringList := TStringList.Create;
  RichEdit1.Lines.SaveToStream(stream);
  stream := transformHyperlinks(stream);
  stringList.LoadFromStream(stream);
  showmessage(stringList.Text);


Lannes - Fr 11.06.10 00:08

Hallo,

du bist der erste der sagt das der verlinkte Code nicht funktioniert :gruebel:

Wie ist Plaintext dabei eingestellt?
Was macht transformHyperlinks?
Welchen der verlinkten Codes hast du probiert, GetRTFFromRichEdit?


LonghornUser - Fr 11.06.10 15:39

Es lag an PlainText, viiiiielen Dank für den Hinweis. Da wäre ich nicht ohne weiteres drauf gekommen :)

Ich hatte nämlich versucht, das ganze umschaltbar zu machen (formatiert VS. plain text). Ich wollte erreichen, das RichEdit, was vielleicht formatierten text enthält, auf Plain text umzuschalten, also komplett die ganze Formatierung zu entfernen. Aber mit der PlainText-Eigenschaft geht das leider nicht. Wie kann man das denn bewerkstelligen?


Lannes - Fr 11.06.10 17:21

Hallo,

PlainText wirkt im Zusammenhang mit Lade- und Save-Routienen(Datei, Stream).
Formatierungen kannst du so entfernen:

Delphi-Quelltext
1:
2:
  RichEdit1.SelectAll;
  RichEdit1.SelText := RichEdit1.Text;
In RichEdit.Text sind die Formatierungscodes nicht enthalten. Eventuell musst du danach alles überformatieren, denn nach dem Austausch über RichEdit.Text ist der gesammte Text wie das erste Zeichen formatiert.

//Edit: willst Du es "umschaltbar" haben, muss nätürlich der formatierte RichEdit-Inhalt gesichert werden, das kannst du mit den Funktionen die ich dir verlinkt habe, über einen String realisieren.