![]() |
Textzeilen umbrechen
Hallo,
ich schreibe gerade eine Edit-Komponente. Sie soll ähnlich wie RichEdit Formatierungen beherrschen. Klappt auch ganz gut. Ich möchte das Ganze aber beschleunigen (ist nämlich immer eine gute Idee :mrgreen: ). Dafür hab ich mir den Zeilenumbruch ausgesucht. Das ist eine ziemlich blöde Sache, ich messe und kürze solange meinen Text (TextExtend), bis der Text kleiner als der verfügbare Platz ist. Das können bei einem langen Text schon mal einige Aufrufe sein. Nun meine Frage: Gibt es eine API-Funktion, die mir sowas ähnliches sagt: Zitat:
Delphi-Quellcode:
Wenn es sowas nicht gibt, hat jemand einen Algorithmus, um diesen Wert schnell zu finden?
function GetLinebreak(DC: HDC; S: PChar; Length: Integer; Width: Integer): Integer;
Gruß xaromz |
Re: Textzeilen umbrechen
Mal 'ne blöde Frage:
Als Basis nutzt du aber schon ein "EDIT" im Sinne der Windows API, oder? Also im Prinzip sowas: Zitat:
|
Re: Textzeilen umbrechen
Hallo xaromz,
schau dir mal die Methode TextWidth() von TCanvas an. Grüße vom marabu |
Re: Textzeilen umbrechen
Hallo,
@Daniel G: Nein, ich benutze kein API-Edit. Ich leite von TCustomControl ab. Wie kann ich denn bei einem "EDIT" (im API-Sinne) einzelne Zeichen formatieren? Geht das überhaupt? :gruebel: Ich kenn mich da nicht so gut aus... @marabu: Genau so mach ich das gerade: Textlänge messen -> zu lang -> Text kürzen, Textlänge messen usw. Das dauert aber lange und ist auch nicht sehr schön. Gruß xaromz |
Re: Textzeilen umbrechen
Hallo xaromz,
Zitat:
marabu |
Re: Textzeilen umbrechen
Hallo,
Zitat:
Meine Vorgehensweise war natürlich vereinfacht ausgedrückt, ich springe beim Verkleinern immer zum nächsten Trennzeichen (Space, Interpunktionszeichen, Trennstrich...). Nur was mache ich, wenn mein Edit 30 Pixel breit ist und jemand "Donaudampfschifffahrtskapitän" eingibt? Da gibt es kein Trennzeichen. Also muss ich doch wieder nachmessen, bis es passt. Ich hab mir schon überlegt ob ich einfach meinen Suchalgorithmus so optimiere: 1) Text messen 2) Text zu lang -> Textlänge halbieren -> Zurück zu 1) 3) Text zu kurz -> Textlänge um 50% vergrössern -> Zurück zu 1) Da fehlt natürlich noch die Abbruchbedingung. Das müsste die Textmessungen im Mittel drastisch verringern Gruß xaromz |
Re: Textzeilen umbrechen
Da ist mir noch etwas eingefallen:
![]() Zitat:
|
Re: Textzeilen umbrechen
Hallo,
danke für den Tipp. Werd ich mir mal ansehen. Gruß xaromz |
Re: Textzeilen umbrechen
Zitat:
![]() |
Re: Textzeilen umbrechen
Hallo,
Zitat:
Gruß xaromz |
Re: Textzeilen umbrechen
Der wichtige Unterschied ist das hier:
Zitat:
|
Re: Textzeilen umbrechen
Zitat:
Aber vermutlich spart man sowieso keine Aufrufe, weil ja auch noch die Formatierung innerhalb einer Zeile verschieden sein kann. |
Re: Textzeilen umbrechen
Hmmmm ... also gegeben hast du
a) einen String und b) die restliche Ausgabebreite in der aktuellen Zeile, und du willst wissen wo du in die nächste Zeile umbrechen musst. -> mit GetTextExtentPoint32 erfährst du nur, ob du ihn umbrechen musst. -> mit GetTextExtentExPoint erfährst du, ob und wenn ja wo du ihn umbrechen musst. In diesem Sinne schlägt GetTextExtentExPoint also zwei Fliegen mit einer Klappe, xaromz braucht ja beide Informationen. |
Re: Textzeilen umbrechen
Zitat:
|
Re: Textzeilen umbrechen
Kan mir mal jemand helfen, das anzuwenden?
Delphi-Quellcode:
Ich dachte so geht es, aber in der for-Zeile meint er, inkompatible Typen. :gruebel:
var
i : Integer; s : string; size : TSize; cntChars : PInteger; alpDx : PInteger; begin GetTextExtentExPoint(dc, PChar(TEXT), length(TEXT), -(PageW * 10) - 100, cntChars, alpDx, size); for i := 0 to length(alpDx) - 1 do begin s := copy(TEXT, alpDx[i], cntChars^); TextOut(dc, 100, -10 * (i + 16), PChar(s), length(s)); end; |
Re: Textzeilen umbrechen
Zitat:
//Edit: Hilft dir das hier? Hab' ich bei Experts Exchange gefunden, müsstest natürlich noch etwas anpassen.
Delphi-Quellcode:
procedure TForm1.but_CustomTextClick(Sender: TObject);
var TextStr: String; Bmp1: TBitmap; numChar, oNum, lines: Integer; aSize: tagSize; begin TextStr := 'Thisisatextstringlongenoughtowrap a couple of times. And'+ 'Moretextherefollowedbevenmore text followed by eveen more text'+ ' followed-by-even-more-text followed by even moore text'; Bmp1 := TBitmap.Create; try Bmp1.Width := 188;// try to have a 3 pixel border, use 182 below Bmp1.Height := 230; Bmp1.Canvas.Font.Name := 'Arial'; Bmp1.Canvas.Font.Size := 11; if Length(TextStr) < 1 then Exit; lines := 0; repeat GetTextExtentExPoint(Bmp1.Canvas.Handle, PChar(TextStr),Length(TextStr),182, @numChar, nil, aSize); oNum := numChar; while (numChar > 1) and not (TextStr[numChar] in [' ','.',',','-','_','?','!','$','(',')']) do Dec(numChar); if numChar = 1 then numChar := oNum; TextOut(Bmp1.canvas.handle,3,(lines*(aSize.cy+8))+3,PChar(TextStr), numChar); Delete(TextStr,1,numChar); Inc(Lines); until Length(TextStr) < 1; Canvas.Draw(530,290, Bmp1); finally FreeAndNil(Bmp1); end; end; ![]() |
Re: Textzeilen umbrechen
Habs rausgefunden:
Delphi-Quellcode:
Hehe. Genau das gleiche habe ich auch gerade gefunden. ;)
i := 0;
s := TEXT; w := (PageW * 10) - 200; repeat GetTextExtentExPoint(dc, PChar(s), length(s), w, @cntChars, nil, size); TextOut(dc, 100, -100 + -i * (Size.cy + 8), PChar(s), cntChars); Delete(s, 1, cntChars); Inc(i); until length(s) < 1; Jetzt müsste man das nur noch so hinbekommen, dass er nicht mitten im Wort umbricht. :? Und Zeilenumbruche im Text (#13#10) berücksichtig werden. Leerzeichen hat sich erledigt:
Delphi-Quellcode:
Nur wie mache ich das mit dem Zeilenumbruch?
repeat
GetTextExtentExPoint(dc, PChar(s), length(s), (PageW * 10) - BORDERLEFT - BORDERRIGHT, @cntChars, nil, size); while (s[cntChars] <> ' ') do Dec(cntChars); TextOut(dc, BORDERLEFT, -BORDERTOP + -i * (Size.cy + 8), PChar(s), cntChars); Delete(s, 1, cntChars); Inc(i); until cntChars < 1; |
Re: Textzeilen umbrechen
Zeilenumbrüche sind auch gelöst. Ich jage den String vorher durch
![]() |
Re: Textzeilen umbrechen
Guten Morgen Michael,
vielleicht doch besser so:
Delphi-Quellcode:
Grüße vom marabu
var
n : Integer; i : Integer; s : string; size : PSize; cntChars : Integer; alpDx : PInteger; begin // ... n := Min(Length(TEXT), cntChars); GetMem(alpDX, n * SizeOf(Integer)); GetMem(size, n * SizeOf(TSIZE)); GetTextExtentExPoint(dc, PChar(TEXT), length(TEXT), -(PageW * 10) - 100, @cntChars, alpDx, size); // ... |
Re: Textzeilen umbrechen
Was wäre daran besser?
|
Re: Textzeilen umbrechen
Ich wollte dich darauf hinweisen, dass du die API-Funktion aus der Schleife nehmen kannst. Rein theoretisch reicht ein einziger Aufruf von GetTextExtentExPoint() aus um deinen Text formatieren zu können.
Freundliche Grüße vom marabu |
Re: Textzeilen umbrechen
Äh, stimmt, die Anzahl der Zeichen, die da reinpassen, ändert sich ja nicht. ;) Danke für den Hinweis.
|
Re: Textzeilen umbrechen
Hallo... ich verstehe die Funktion noch nicht ganz. Was genau wird mir in dem array of integer zurückgegeben?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:58 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