AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Bounding rectangle eines fromatierten RTF-Textes ermitteln.
Thema durchsuchen
Ansicht
Themen-Optionen

Bounding rectangle eines fromatierten RTF-Textes ermitteln.

Ein Thema von alzaimar · begonnen am 2. Sep 2005 · letzter Beitrag vom 2. Sep 2005
Antwort Antwort
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#1

Bounding rectangle eines fromatierten RTF-Textes ermitteln.

  Alt 2. Sep 2005, 07:05
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:
Var
  P : TPoint;
Begin
  reContainer.Perform (EM_POSFROMCHAR,LongInt (@P), 32767)
 ...
In P.Y steht dann die Höhe des Texts (wenn dieser mit einer Leerzeile abschliesst).
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:
Function RTF_GetFormatedTextRect (Const aText : String; aCanvasRect : TRect) : TRect; Sie liefert dann den Umriss des formatierten Texts in Pixeln.

Danke für die Mühe

[edit]EM_GETRECT in EM_POSFROMCHAR geändert[/edit]
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von BrunoT
BrunoT

Registriert seit: 23. Jan 2003
Ort: Sandbeiendorf
360 Beiträge
 
Delphi 8 Professional
 
#2

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 07:14
Hi erstelle doch ein Richedit mit

visible;=false;

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.

mfg

BrunoT
Holger

EDV- Ende der Vernunft
Meine Calcedit-Kompo
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#3

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 07:48
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}
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#4

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 08:23
Hi alzaimar,

Zitat von alzaimar:
Ich benötige die Höhe des formatierten Textes. Das geht bei einem nicht imaginären TRichEdit über den Aufruf
Delphi-Quellcode:
Var
  P : TPoint;
Begin
  reContainer.Perform (EM_GETRECT,Integer (@P), 32767)
 ...
Müsste der Aufruf, damit er keine Speicherverletzung produziert, nicht so aussehen?

Delphi-Quellcode:
var
  r: TRect;
begin
  re.Perform(EM_GETRECT, 0, Integer(@r));
end;
Geliefert wird da aber das formatting rectangle - und das ist laut PSDK identisch zur client area vom richedit, wenn du es nicht änderst.

Zitat von alzaimar:
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.
Du musst dein control als message-only-window erzeugen:

Delphi-Quellcode:
var
  re: TRichEdit;
begin
  re := TRichEdit.CreateParented(HWND(-3));
end;
Bis zu deiner Funktion RTF_GetFormattedTextRect() bist du dann aber immernoch ein Stück unterwegs...

Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 09:01
Wie sieht es aus mit der Meldung MSDN-Library durchsuchenEM_FORMATRANGE - die ist zwar eigentlich nur für den Druck gedacht, aber das heißt ja vielleicht nichts.

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.
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 09:24
So scheint's zu funktionieren:
Delphi-Quellcode:
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;
//EDIT: Berechnet aber offensichtlich nur die Höhe ...

[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:
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;
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).
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Bounding rectangle eines fromatierten RTF-Textes ermitte

  Alt 2. Sep 2005, 09:47
Goil! Keiner arbeitet, Alle sind im Forum und helfen....

@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 ) 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 )

Schönen Tag (Hier in Berlin ist es --- Heeeeiiiiiisssss!)

wünscht

der "als Eimer"
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz