![]() |
Bounding rectangle eines fromatierten RTF-Textes ermitteln.
Seit gestern versuche ich das.
Gegeben sei ein RTF-Text sowie ein imaginäres TRichEdit mit einer definierten Breite. Dahinein plaziere ich den RTF-formatierten Text. Ich benötige die Höhe des formatierten Textes. Das geht bei einem nicht imaginären TRichEdit über den Aufruf
Delphi-Quellcode:
In P.Y steht dann die Höhe des Texts (wenn dieser mit einer Leerzeile abschliesst).
Var
P : TPoint; Begin reContainer.Perform (EM_POSFROMCHAR,LongInt (@P), 32767) ... Super, das will ich jetzt OHNE ein TRichEdit realisieren. Wenn ich mir einfach eine Instanz erstelle (Parent = Nil), wird sofort die Notbremse (Exception) beim Setzen der Lines-Eigenschaft gezogen. Weiss jemand wie ich das sonst hinbekomme, oder mir ein TRichEdit mit einem Parent bastle, ohne Bezug zu einem Formular nehmen zu müssen? Ich möchte sozusagen eine Funktion implementieren:
Delphi-Quellcode:
Sie liefert dann den Umriss des formatierten Texts in Pixeln.
Function RTF_GetFormatedTextRect (Const aText : String; aCanvasRect : TRect) : TRect;
Danke für die Mühe [edit]EM_GETRECT in EM_POSFROMCHAR geändert[/edit] |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
Hi erstelle doch ein Richedit mit
visible;=false; :stupid: Das kannst Du dann zum Berechnen der Texthöhe nehmen. Oder Schau Dir mal die Funktion Drawtext mit DT_CALCRECT als Parameter im Windows SDK an. Diese Funktion gibt ein Rechteck zurück, welches die Eckkoordinaten des Textes enthält, wenn der Text geschrieben werden würde. :zwinker: mfg BrunoT |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
Hi BrunoT.
Nee, mit Visible=False geht das nicht, weil sich dann das blöde Ding weigert, die korrekten Werte zu berechnen. Es denkt sich wohl: Wer mich nicht sieht, merkt auch nicht, das ich nix tue... Ausserdem will ich gerade KEIN TRechEdit auf einer Form haben. Der zweite Tipp bezieht sich aber nicht auf RTF-formatierte Texte, oder doch? Wie hoch ist dieser Text bei einer Boundingrect, die 150 pixel breit ist?
Code:
{\rtf1\ansi\ansicpg1252\deff0\deflang1031{\fonttbl{\f0\fswiss
\fcharset0 Arial;}{\f1\fswiss\fprq2\fcharset0 Microsoft Sans Serif;}} {\colortbl ;\red0\green0\blue128;}{\*\generator CSIBERLIN;} \viewkind4\uc1\pard\cf1\b\i\f0\fs20 Dies ist eine Überschrift\cf0\b0\i0\par \f1 Und das hier nicht, denn es ist der Text\f0\par} |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
Hi alzaimar,
Zitat:
Delphi-Quellcode:
Geliefert wird da aber das formatting rectangle - und das ist laut PSDK identisch zur client area vom richedit, wenn du es nicht änderst.
var
r: TRect; begin re.Perform(EM_GETRECT, 0, Integer(@r)); end; Zitat:
Delphi-Quellcode:
Bis zu deiner Funktion RTF_GetFormattedTextRect() bist du dann aber immernoch ein Stück unterwegs...
var
re: TRichEdit; begin re := TRichEdit.CreateParented(HWND(-3)); end; Grüße vom marabu |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
Wie sieht es aus mit der Meldung
![]() Ich meine mich zu erinnern, dass wenn man dem ein "unendlich" hohes Rechteck in FORMATRANGE.rc vorwirft, dass dann der gesamte Text formatiert wird und FORMATRANGE.rc.right und FORMATRANEG.rc.bottom entsprechend angepasst werden. Du musst halt nur ein bisschen zwischen Pixeln und Twips hin und her rechnen. |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
So scheint's zu funktionieren:
Delphi-Quellcode:
//EDIT: Berechnet aber offensichtlich nur die Höhe ...
function GetRichEditTextExtent(hRichEdit: HWND; nWidth: integer): TPoint;
var dc: HDC; fr: TFormatRange; res: TPoint; rv: integer; begin dc := GetDC(hRichEdit); try res.x := GetDeviceCaps(dc, LOGPIXELSX); res.y := GetDeviceCaps(dc, LOGPIXELSY); fr.hdc := dc; fr.hdcTarget := dc; fr.rc := Rect(0, 0, MulDiv(nWidth, 1440, res.x), $1000000); fr.rcPage := fr.rc; fr.chrg.cpMin := 0; fr.chrg.cpMax := SendMessage(hRichEdit, WM_GETTEXTLENGTH, 0, 0); rv := SendMessage(hRichEdit, EM_FORMATRANGE, 0, LPARAM(@fr)); SendMessage(hRichEdit, EM_FORMATRANGE, 0, 0); Assert(rv >= fr.chrg.cpMax); Result.x := MulDiv(fr.rc.Right, res.x, 1440); Result.y := MulDiv(fr.rc.Bottom, res.y, 1440); finally ReleaseDC(hRichEdit, dc); end; end; [Nachtrag] So berechnet er auch die Breite, aber perfekt ist's immer noch nicht wegen der Zeilenumbrüche. Diese Funktion ermittelt die "minimale Breite" die nötig ist, um die berechnet Höhe zu halten. Das kann anders aussehen als bei dir auf dem Bildschirm.
Delphi-Quellcode:
Eine exakte Lösung wäre z.B., mit bekannter Breite und Höhe eine Bitmap zu erzeugen und das RichEdit dort hinein zeichnen zu lassen. Danach müsste man dann den rechten Rand dieser Bitmap überprüfen (ziemlich aufwändig).
function GetRichEditTextExtent(hRichEdit: HWND; nWidth: integer): TPoint;
var dc: HDC; fr: TFormatRange; res: TPoint; txl: integer; rv: integer; wmin, wmid, wmax: integer; function CalcHeight(w: integer): integer; begin fr.hdc := dc; fr.hdcTarget := dc; fr.rc := Rect(0, 0, MulDiv(w, 1440, res.x), $1000000); fr.rcPage := fr.rc; fr.chrg.cpMin := 0; fr.chrg.cpMax := txl; rv := SendMessage(hRichEdit, EM_FORMATRANGE, 0, LPARAM(@fr)); Assert(rv >= fr.chrg.cpMax); Result := MulDiv(fr.rc.Bottom, res.y, 1440); end; begin dc := GetDC(0); try res.x := GetDeviceCaps(dc, LOGPIXELSX); res.y := GetDeviceCaps(dc, LOGPIXELSY); txl := SendMessage(hRichEdit, WM_GETTEXTLENGTH, 0, 0); Result.X := nWidth; Result.Y := CalcHeight(Result.X); wmin := 1; wmax := nWidth; while wmin <= wmax do begin wmid := (wmin + wmax) div 2; if CalcHeight(wmid) <= Result.Y then begin Result.X := wmid; wmax := wmid - 1; end else wmin := wmid + 1; end; finally SendMessage(hRichEdit, EM_FORMATRANGE, 0, 0); ReleaseDC(0, dc); end; end; |
Re: Bounding rectangle eines fromatierten RTF-Textes ermitte
Goil! Keiner arbeitet, Alle sind im Forum und helfen.... :thumb:
@marabu: Ich hatte mich vertippt, die message lautet EM_GETPOSFROMCHAR, denn mit EM_GETRECT geht das nicht, frag mich nicht wieso. Ich benötige nur die Höhe des RTF-Textes, und wenn ich die Cursorposition des letzten Zeichens abfrage (vorausgesetzt, ich habe eine leere Zeile am ende des Textes), dann entspricht P.Y genau der Texthöhe... Nach der 'ControlParented' Lösung habe ich (zwar nicht so richtig :oops:) gesucht, aber ich wusste, das mir hier einer helfen kann. Danke! @Flocke: Deine Funktion in Verbindung mit dem 'unsichtbaren' TRichEdit vom marabu ist DIE Lösung. Die exakte Breite ist derzeit nicht nötig. Die Problemstellung ist: Ich habe ein Panel mit einer definierten Breite, da soll das RTF rein, nur wie hoch muss das Panel sein, damit alles reinpasst... Aber auch ein fettes Danke! Ich denke, die 'exakte Breite' ist der maximale X Wert, den mir die EM_GETPOSFROMCHAR-Geschichte liefert. Das ist zwar billig und lahm, aber wir haben ja mittlerweile GHZe im Überangebot. Nochmal! Danke Euch beiden! (So, reicht :zwinker: ) Schönen Tag (Hier in Berlin ist es --- Heeeeiiiiiisssss!) wünscht der "als Eimer" |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz