Autor |
Beitrag |
Daniel L.
      
Beiträge: 140
Erhaltene Danke: 14
W7, W8
TurboD Prof, Delphi Community
|
Verfasst: Mi 27.10.10 17:29
Hallo!
Kann man die Länge in Pixel einer formatierten Textzeile in einer RichEdit bestimmen?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| with RichEdit do begin SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taCenter; Lines.Add('Wie lang ist eigentlich diese Zeile in Pixeln'); end; |
Schon mal Danke + Gruss: Daniel
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Mi 27.10.10 18:23
Mittels Canvas.TextWidth;
hier ein beispiel:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var bmp := TBitmap; begin bmp := TBitmap.Create(); bmp.canvas.Font := Richedit1.Font; laenge := bmp.canvas.textwidth(deine_Zeile); bmp.free end; |
das noch mit entsprechenden Ressourcenschutzblöcken ausstatten und voilá!
lg elundril
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
jaenicke
      
Beiträge: 19321
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 27.10.10 19:40
In einem RichEdit kann der Text aber beliebig formatiert sein.
Ich vermute daher, dass du da manuell durchgehen musst und die Zeichen entsprechend ihrer Formatierung behandeln musst. Eine fertige Routine gibt es dafür AFAIK nicht.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Mi 27.10.10 23:50
Daniel L. hat folgendes geschrieben : | Kann man die Länge in Pixel einer formatierten Textzeile in einer RichEdit bestimmen? |
Beispiel:
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:
| procedure TMainform.Button1Click(Sender: TObject); var PunktZeile : TPoint; PunktAnfang : TPoint; CharPos : integer; begin CharPos := 0; SendMessage(RichEdit1.Handle, EM_PosFromChar, wParam(@PunktAnfang), lParam(CharPos)); CharPos := SendMessage(RichEdit1.Handle, EM_LineLength, 0, 0); SendMessage(RichEdit1.Handle, EM_PosFromChar, wParam(@PunktZeile), lParam(CharPos)); Label1.Caption := 'Anzahl Zeichen: ' + IntToStr(CharPos); Label2.Caption := 'Breite der Zeile (Space + Text): ' + IntToStr(PunktZeile.X); Label3.Caption := 'Breite der Zeile (nur Text): ' + IntToStr(PunktZeile.X - PunktAnfang.X + 1); end;
procedure TMainform.Button2Click(Sender: TObject); begin with RichEdit1 do begin Clear; SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taCenter; Lines.Add('Wie lang ist eigentlich diese Zeile in Pixeln?'); end; end; |
Im Beispiel gehe ich von nur einer Zeile aus, also ggf. anpassen.
Edit1: Ob die Zeichenbreite des letzten Zeichens in den Werten eingerechnet ist, habe ich noch nicht geprüft.
@elundril: Deine Prozedur scheint falsche Werte zu liefern (203). Ich ermittele hingegen 509, was wohl eher hinkommen dürfte.
Edit2: Das letzte Zeichen ist mit eingerechnet, was man leicht überprüfen kann, wenn der Text aus nur einem Zeichen besteht.
|
|
jaenicke
      
Beiträge: 19321
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 28.10.10 05:51
Stimmt, auf die Idee bin ich gar nicht gekommen. Über die Position des ersten und letzten Zeichens lässt sich die Breite natürlich berechnen. 
|
|
Daniel L. 
      
Beiträge: 140
Erhaltene Danke: 14
W7, W8
TurboD Prof, Delphi Community
|
Verfasst: Do 28.10.10 09:12
@Gerd: Vielen Dank für die kompetente Antwort!
Verrätst du mir noch, was ich anpassen muss, um z.B. die 3. Zeile zu 'messen'?
Danke + Gruss: Daniel
|
|
jaenicke
      
Beiträge: 19321
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 28.10.10 11:11
CharPos musst du (bezogen auf das Beispiel) entsprechend setzen.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Do 28.10.10 13:14
Daniel L. hat folgendes geschrieben : | Verrätst du mir noch, was ich anpassen muss, um z.B. die 3. Zeile zu 'messen'? |
Ich komme erst heute Nacht dazu, weiter zu programmieren. Jetzt stehen erst einmal zwei Stunden Gassigänge mit meiner verspielten Schäferhündin und ein längerer Zahnarztbesuch an.
|
|
Daniel L. 
      
Beiträge: 140
Erhaltene Danke: 14
W7, W8
TurboD Prof, Delphi Community
|
Verfasst: Do 28.10.10 19:16
hm, intern scheint TRichEdit für jede Textzeile 2 weitere Charakters dazuzuzählen (vielleicht #10 und #13 ?)
Folgende Funkion funzt bei mir:
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:
| function TForm1.GetZeilenBreite (Zeile : integer) : integer; var i, CharCount : integer; ZeileAnfang, ZeileEnde : TPoint; begin
if (zeile > (RichEdit1.Lines.Count - 1)) or (zeile < 0) then begin result := -1; exit; end;
CharCount := 0;
for I := 0 to zeile - 1 do inc (CharCount, length (RichEdit1.Lines [i]) + 2);
SendMessage (RichEdit1.Handle, EM_PosFromChar, wparam (@ZeileAnfang), CharCount); CharCount := CharCount + SendMessage (RichEdit1.Handle, EM_LineLength, CharCount, 0); SendMessage(RichEdit1.Handle, EM_PosFromChar, wParam (@ZeileEnde), CharCount); result := ZeileEnde.X - ZeileAnfang.X; end;
procedure TForm1.Button1Click(Sender: TObject); begin showmessage ('Zeilenbreite = ' + Inttostr (GetZeilenBreite (1))); end; |
Ich hoffe, dass das auch programmiertechnisch in Ordnung ist und dass Gerd kein Zahnschmerzen hat
Gruss: Daniel
|
|
jaenicke
      
Beiträge: 19321
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 28.10.10 19:29
Daniel L. hat folgendes geschrieben : | Ich hoffe, dass das auch programmiertechnisch in Ordnung ist und dass Gerd kein Zahnschmerzen hat |
Ich bekomm da immer eher Bauchschmerzen.
Zur Sache:
Du brauchst keine Schleife. Mit EM_LINEINDEX bekommst du das erste Zeichen einer Zeile:
msdn.microsoft.com/e...761611(v=VS.85).aspx
Steht alles in der Doku.
// EDIT:
Ach ja: Die beiden Zeichen pro Zeile mehr sind in der Tat die Zeilenumbruchszeichen.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Do 28.10.10 20:17
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Do 28.10.10 23:51
So, hier ist meine Lösung, die auch Zeilenumbrüche durch WordWrap richtig behandelt. Bitte beachten, daß die Funktion verschieden aufgerufen werden kann:
1. mit Zeile = - 1: liefert die Zeilenanzahl zurück
2. mit Zeilennummer, aber NurText = false: Breite der Zeichenkette plus dem Leerraum vor dem 1. Zeichen
3. mit Zeilennummer, aber NurText = true: Breite der Zeichenkette
NurText kann beim Aufruf weggelassen werden. Dann arbeitet die Funktion mit NurText = true
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: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131:
| unit Main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type TMainform = class(TForm) RichEdit1: TRichEdit; Button1: TButton; Label1: TLabel; Label2: TLabel; Button2: TButton; Label3: TLabel; Edit1: TEdit; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private public function ErmittelnTextBreite(Handle : THandle; Zeile : integer; NurText : boolean = true): integer; end;
var Mainform: TMainform;
implementation
{$R *.dfm}
function TMainform.ErmittelnTextBreite(Handle : THandle; Zeile : integer; NurText : boolean = true): integer; var AnzZeilen : integer; ErstesZeichen : integer; LetztesZeichen : integer; PunktStart : TPoint; PunktEnde : TPoint; begin Result := - 1; AnzZeilen := SendMessage(Handle, EM_GetLineCount, 0, 0);
if Zeile = - 1 then Result := AnzZeilen else begin ErstesZeichen := SendMessage(Handle, EM_LineIndex, wParam(Zeile), 0); LetztesZeichen := SendMessage(Handle, EM_LineLength, wParam(ErstesZeichen), 0); SendMessage(Handle, EM_PosFromChar, wParam(@PunktStart), lParam(ErstesZeichen)); SendMessage(Handle, EM_PosFromChar, wParam(@PunktEnde), lParam(ErstesZeichen + LetztesZeichen));
if PunktStart.Y <> PunktEnde.Y then SendMessage(Handle, EM_PosFromChar, wParam(@PunktEnde), lParam(ErstesZeichen + LetztesZeichen - 1));
if NurText then Result := PunktEnde.X - PunktStart.X + 1 else Result := PunktEnde.X; end; end;
procedure TMainform.Button1Click(Sender: TObject); var Zeile : integer; AnzZeilen : integer; Breite : integer; begin if not TryStrToInt(Trim(Edit1.Text), Zeile) then ShowMessage('Fehler: Keine Ziffer im Edit-Feld!') else begin AnzZeilen := ErmittelnTextBreite(RichEdit1.Handle, - 1); Label1.Caption := 'Anzahl Zeilen: ' + IntToStr(AnzZeilen); if Zeile > (AnzZeilen - 1) then ShowMessage('Fehler: RichEdit enthält nicht so viele Zeilen!') else begin Breite := ErmittelnTextBreite(RichEdit1.Handle, Zeile, false); Label2.Caption := 'Breite (Space am Angfang + Text): ' + IntToStr(Breite); Breite := ErmittelnTextBreite(RichEdit1.Handle, Zeile); Label3.Caption := 'Breite (nur Text): ' + IntToStr(Breite); end; end;
end;
procedure TMainform.Button2Click(Sender: TObject); var Text1 : string; Text2 : string; begin Text1 := 'Wie lang ist eigentlich diese Zeile in Pixeln?'; Text2 := Text1 + Text1 + Text1; with RichEdit1 do begin Clear; SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taCenter; Lines.Add(Text1); SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taCenter; Lines.Add(Text2); SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taLeftJustify; Lines.Add(Text1); SelAttributes.Color := clred; SelAttributes.Size := 20; Paragraph.Alignment := taRightJustify; Lines.Add(Text1); end; end;
end. |
Edit1: Fehler in Zeile 89 korrigiert
|
|
Daniel L. 
      
Beiträge: 140
Erhaltene Danke: 14
W7, W8
TurboD Prof, Delphi Community
|
Verfasst: Fr 29.10.10 09:39
Oh ja, stimmt, ohne die WordWrap Beachtung kämen ja ggf. falsche Werte raus.
EM_GetLineCount scheint immer eine um 1 grössere Zahl zu liefern, man muss also wieder 1 subtrahieren, oder man nimmt Richedit.lines.count
Gerd Kayser hat folgendes geschrieben : |
Delphi-Quelltext 1: 2:
| if NurText then Result := PunktEnde.X - PunktStart.X + 1 |
|
Bist du sicher, dass das stimmt?
Für eine leere Textzeile kommt dann 1 raus!
Gruss: Daniel
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Fr 29.10.10 11:47
Daniel L. hat folgendes geschrieben : | EM_GetLineCount scheint immer eine um 1 grössere Zahl zu liefern, man muss also wieder 1 subtrahieren, oder man nimmt Richedit.lines.count |
Das ist so nicht richtig. Es sind zwar z. B. 6 Zeilen mit Text vorhanden, aber es gibt noch eine 7. (leere) Zeile, in die Du mit dem Cursor springen kannst. Wenn Du in dieser Leerzeile die Backspace-Taste drückst, so daß der Cursor in der vorhergehenden Zeile direkt hinter dem Text steht, erst dann stimmen die Werte von Richedit.lines.count und EM_GetLineCount überein.
Zitat: | Delphi-Quelltext 1: 2:
| if NurText then Result := PunktEnde.X - PunktStart.X + 1 |
Bist du sicher, dass das stimmt?
Für eine leere Textzeile kommt dann 1 raus! |
Folgender Fall:
Eine Zeile ist linksbündig (taLeftJustify) ausgerichtet. Ohne "+ 1" ergäben sich dann folgende Werte für den String:
Nur Text: 508
aber Text plus Leerraum davor: 509
Das ist jetzt Auslegungssache, ob man das Pixel vor dem Text zur Textbreite hinzuzählt oder nicht. Du kannst das "+ 1" weglassen oder alternativ die Funktion am Ende um folgende Anweisung ergänzen:
Delphi-Quelltext 1: 2:
| if Result = 1 then Result := 0; | Das überlasse ich Dir. Ist wie gesagt eine reine Interpretationssache.
|
|
|