Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Wordwrap umbruch (https://www.delphipraxis.net/198619-wordwrap-umbruch.html)

EWeiss 19. Nov 2018 14:04

Wordwrap umbruch
 
Bei einer Zuweisung von Wordwrap an einem Label wird der gesamte string umgebrochen abhängig von der weite des Controls.
Wie kann ich jetzt verhindern das er auf mehr wie 2 Zeilen umbricht?
Wenn mehr wie 2 Zeilen dann soll ein Ellipsis angefügt werden.

gruss

EWeiss 19. Nov 2018 16:20

AW: Wordwrap umbruch
 
Um was es mir geht.
Ich möchte einen string ohne es zu sehr zu komplizieren so auslegen das er die Eigenschaften vom Label übernimmt inkl. Zeilenumbruch usw.

Delphi-Quellcode:
function TAudioSessionVolume.AudioSessionInfo: TAudioSessionInfo;
var
  Lbl: TLabel;
  tmpStr: string;
  bNull: BOOL;
  i: integer;
begin

  Result := NullAudioSessionInfo;

  bNull := False;

  tmpStr := ExtractFileExt(FAudioSessionInfo.DisplayName);
  if Length(tmpStr) > 1 then
    tmpStr := ChangeFileExt(FAudioSessionInfo.DisplayName, '')
  else
    tmpStr := FAudioSessionInfo.DisplayName;

  if tmpStr <> '' then
  begin
    Lbl := TLabel.Create(nil);
    Lbl.Caption := tmpStr;
    Lbl.AutoSize := True;

    // check for blank
    for i := 1 to Length(tmpStr) do
    begin
      if tmpStr[i] = ' ' then
        bNull := True;
    end;

    if not bNull then
    begin
      if (Lbl.Width > ParentWidth) and (ParentWidth > 0) then
      begin
        Lbl.Caption := Lbl.Caption + '...';
        while Lbl.Width > ParentWidth do
          Lbl.Caption := Copy(Lbl.Caption, 1, Length(Lbl.Caption) - Lbl.Font.Size) + '...';
      end;
    end;

    Lbl.WordWrap := bNull;
    FAudioSessionInfo.WordWrap := bNull;
    FAudioSessionInfo.DisplayName := Lbl.Caption;
    tmpStr := '';
    FreeAndNil(Lbl);

    Result := FAudioSessionInfo;
  end;
end;
Ich prüfe zuerst ob der string 'blank' enthält also ein Leerzeichen.
Wenn eine Leerzeichen existiert soll der string umgebrochen werden dazu setze ich dann Lbl.Wordwrap auf true.
Wenn der string kein 'blank' enthält und länger ist wie die gesamte weite des Controls (ParentWidth) soll Ellipsis Character angehängt werden. (funktioniert und ist in Ordnung).

Wenn der string mehrere 'blank' enthält soll er maximal 2 Zeilen umbrechen und dann ein Ellipsis Character angehängt werden das funktioniert nicht wie gewünscht.
Der WordWrap scheint aber nicht wirklich vom string angenommen zu werden.
Wo liegt mein Denkfehler?

Das Problem sieht man im Anhang.

gruss

KodeZwerg 19. Nov 2018 19:14

AW: Wordwrap umbruch
 
Es ist nur eine Vermutung aber ich glaube Autosize und Wordwrap vertragen sich nicht.

edit
Schau mal was ich gefunden habe, vielleicht hilft es Dir...

EWeiss 19. Nov 2018 21:02

AW: Wordwrap umbruch
 
Zitat:

Es ist nur eine Vermutung aber ich glaube Autosize und Wordwrap vertragen sich nicht.
Hat damit nichts zu tun.
Wenn ich Autosize nicht auf true setze wird die Höhe des Label nicht verändert die ich dann benötige um beide Zeilen nach dem Umbruch anzuzeigen.
Siehe Zitat deines links..
Zitat:

Wenn WordWrap den Wert True hat, ist die Breite des Steuerelements fest. Ist AutoSize ebenfalls True, bewirken Änderungen am Text, dass das Steuerelement in der Höhe angepasst wird.
Ich denke muss das mit dem Label verwerfen das macht so keinen sinn da mir die Umbrüche im String nicht addiert werden.

Delphi-Quellcode:
Lbl.WordWrap := bNull;
FAudioSessionInfo.DisplayName := Lbl.Caption;
mag zwar die höhe des Labels ändern addiert aber nicht den Umbruch in dieser form "13#10" zu meinem Label.
Der Label sähe dann immer noch so aus.. "Emil's MediaPlayer" und nicht wie er sollte ('Emil's' + 13#10 + 'MediaPlayer')

Da ich den String nachher nach GDI+ schicken muss und mir der Umbruch fehlt im string wird das nix.
Ich dachte das die property WordWrap des Labels das automatisch macht (versteckt) scheint aber nicht so.

Auf Deutsch.. Der Zeilenumbruch hat keinerlei Effekt auf den zurückgegebenen String "FAudioSessionInfo.DisplayName"

gruss

TiGü 19. Nov 2018 22:11

AW: Wordwrap umbruch
 
Du möchtest also alle Leerzeichen in einem String mit einem Zeilenumbruch austauschen?:roll:

http://docwiki.embarcadero.com/Libra...Utils.WrapText

EWeiss 19. Nov 2018 22:16

AW: Wordwrap umbruch
 
Zitat:

Zitat von TiGü (Beitrag 1418483)
Du möchtest also alle Leerzeichen in einem String mit einem Zeilenumbruch austauschen?:roll:

http://docwiki.embarcadero.com/Libra...Utils.WrapText

Nein.. sorry wenn das so rübergekommen ist.

Ich möchte den gesamten Text umbrechen und wenn die Zeilenanzahl 2 erreicht ist Ellipsis Character anhängen.
Danach darf kein weiterer Umbruch mehr stattfinden.

gruss

TiGü 20. Nov 2018 10:35

AW: Wordwrap umbruch
 
Delphi-Quellcode:
program WrapTextProject;

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.SysUtils,
  System.StrUtils;

const
  cText = 'The rain in Spain falls mainly on the plain.';

var
  MyWrapedText, MyWrapedWithEllipsisText: string;
  I, SplitPoints: Integer;

begin
  try
    Writeln('Org: ' + sLineBreak, cText, sLineBreak);

    MyWrapedText := WrapText(cText, sLineBreak, [' '], 15);
    Writeln('Wraped: ' + sLineBreak, MyWrapedText, sLineBreak);

    MyWrapedWithEllipsisText := '';
    SplitPoints := 0;
    for I := 1 to Length(MyWrapedText) do
    begin
      if IsDelimiter(sLineBreak, MyWrapedText, I) then
      begin
        Inc(SplitPoints);

        if SplitPoints > 2 then
        begin
          MyWrapedWithEllipsisText := MyWrapedText;
          SetLength(MyWrapedWithEllipsisText, I + 1);
          MyWrapedWithEllipsisText := MyWrapedWithEllipsisText + '...';
          Break;
        end;

      end;
    end;

    Writeln('Wraped with Ellipsis: ' + sLineBreak, MyWrapedWithEllipsisText, sLineBreak);

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
Ausgabe:

Code:
Org:
The rain in Spain falls mainly on the plain.

Wraped:
The rain in
Spain falls
mainly on the
plain.

Wraped with Ellipsis:
The rain in
Spain falls
...

DieDolly 20. Nov 2018 10:37

AW: Wordwrap umbruch
 
Ich weiß nicht ob ich das richtig verstanden habe.
Wenn ja dann muss AutoSize auf False, WordWrap auf True und dann ziehst du das Label so groß wie du es brauchst.

hoika 20. Nov 2018 10:57

AW: Wordwrap umbruch
 
Hallo,
Zitat:

Auf Deutsch.. Der Zeilenumbruch hat keinerlei Effekt auf den zurückgegebenen String "FAudioSessionInfo.DisplayName"
Das ist richtig. Wäre auch schlimm (unschön), wenn in das Label was reingeschrieben wird
und beim Auslesen es eine Rolle spielt, wo groß das Label ist.
Bei einem Memo ist das auch auch so.

EWeiss 20. Nov 2018 13:24

AW: Wordwrap umbruch
 
Ich weis was WrapText ist aber diese API ist nicht die Lösung.
Ich sagte ja schon die Anzahl der Zeilen "2" darf nicht überschritten werden
außerdem wird bei WrapText die gesamte breite des Textes zur weite des Controls nicht berücksichtig.
Ellipsis macht nur sinn wenn der String in der 2 Zeile die weite des Controls überschreitet.

Meine Frage!
Zitat:

Bei einer Zuweisung von Wordwrap an einem Label wird der gesamte string umgebrochen abhängig von der weite des Controls.
Wie kann ich jetzt verhindern das er auf mehr wie 2 Zeilen umbricht?
Wenn mehr wie 2 Zeilen dann soll ein Ellipsis angefügt werden.
Zitat:

Wenn ja dann muss AutoSize auf False, WordWrap auf True und dann ziehst du das Label so groß wie du es brauchst.
Nein die weite des Control ist fix da ist nix mit ziehen und AutoSize muss true sein.

Zitat:

Das ist richtig. Wäre auch schlimm (unschön), wenn in das Label was reingeschrieben wird
Es soll ja nichts reingeschrieben sondern der Label umgebrochen werden.

Siehe..
Delphi-Quellcode:
 Umbruch := 'Emil''s' + 13#10 + 'MediaPlayer';
Zitat:

und beim Auslesen es eine Rolle spielt, wo groß das Label ist.
Was geschieht hier bei der Berechnung wenn AutoSize nicht True ist?
Delphi-Quellcode:
Lbl.Caption := Copy(Lbl.Caption, 1, Length(Lbl.Caption) - Lbl.Font.Size) + '...';


Werde den String splitten und die länge sowie den Umbruch von Hand berechnen.
Der Label hat sich dann erledigt.

gruss

Delphi.Narium 20. Nov 2018 13:50

AW: Wordwrap umbruch
 
Nur so 'ne Idee zum Weiterforschen:

Ein TMemo nehmen, dessen Breite so angepasst wird, dass es die für die Label.Caption benötigte Breite bekommt. Schrifttyp, -größe ... dem Label anpassen. WordWrap = True.

Nun Label.Caption Memo.Text zuweisen.

Das Memo bricht nun den Text selbst um. Wenn Memo.Lines.Count nun größer 2 wird, dann die ersten beiden Zeilen aus dem Memo nehmen und Ellipsis Character dranhängen, Label.Caption zuweisen.

Dadurch wird dann auch die (je nach Schrifttyp) unterschiedliche Breite einzelner Buchstaben berücksichtigt und man muss da keine eigene Berechnungsroutine finden / entwickeln.

Das Memo muss / kann ja "irgendwo unsichtbar" im Programm "rumhängen".

Zugegeben: Elegant scheint mir das erstmal so noch nicht, aber eventuell kannst Du dadraus ja was machen.

EWeiss 20. Nov 2018 13:57

AW: Wordwrap umbruch
 
Jo wäre eine alternative. Danke.
Wenn es mit den Berechnungen zu kompliziert wird genau das wollte ich mir mit dem Label ersparen
das ganze hin und her Splitten, RightTrim, Umbrechen, Font zuweisen usw..

gruss

DeddyH 20. Nov 2018 14:03

AW: Wordwrap umbruch
 
Ließe sich da nichts mit DrawText und den entsprechenden Formaten machen?

EWeiss 20. Nov 2018 14:11

AW: Wordwrap umbruch
 
Zitat:

Zitat von DeddyH (Beitrag 1418537)
Ließe sich da nichts mit DrawText und den entsprechenden Formaten machen?

Ich verwende ja DrawText GDI+
Delphi-Quellcode:
      gSprSession.GD_DrawTextToCtrlEx(HSprSession, PWideChar(Trim(MainClass.DeviceName)), x, y,
        ParentWidth, bh, gSprSession.GD_ARGB(255, 255, 255, 255), PWideChar(FontName), nil, 13,
        ID, GS_VISIBLE, 0, Ord(StringAlignmentCenter));
Ich möchte aber diese Funktion nicht auf WordWrap erweitern deshalb muss der String vorbereitet werden.
Er wird dann nach setzen aller benötigten Formate mit GdipDrawString gezeichnet.

gruss

Schokohase 20. Nov 2018 14:15

AW: Wordwrap umbruch
 
*nix*

EWeiss 20. Nov 2018 14:22

AW: Wordwrap umbruch
 
Zitat:

Zitat von Schokohase (Beitrag 1418540)
Aber sollte dieses GDI+ DrawString nicht genau alles von Haus aus bieten?

Wrapping, Ellipsis?

Laut Dokumentation soll die das machen können.

Weil ich es nicht möchte..
Zitat:

Ich möchte aber diese Funktion nicht auf WordWrap erweitern deshalb muss der String vorbereitet werden.
Das es von Haus aus geht ist mir bekannt.

Oder warum glaubst du habe ich extra ein Format dafür addiert?
Delphi-Quellcode:
      else if UseStrFormat = GD_Ellipsis then
      begin
        GdipCheck(GdipCreateStringFormat(0, 0, strformat));
        GdipCheck(GdipSetStringFormatFlags(strformat, StringFormatFlagsNoWrap));
        GdipCheck(GdipSetStringFormatAlign(strformat, StringAlignmentNear));
        GdipCheck(GdipSetStringFormatLineAlign(strformat, StringAlignmentNear));
        GdipCheck(GdipSetStringFormatTrimming(strformat, StringTrimmingEllipsisCharacter));
      end
gruss

Schokohase 20. Nov 2018 14:28

AW: Wordwrap umbruch
 
*nix*

EWeiss 20. Nov 2018 14:32

AW: Wordwrap umbruch
 
Zitat:

ich entschuldige mich dafür in aller Form.
Hast du nicht geschrieben
Nicht nötig.. Aber ich sagte ja vorher schon und ja habe ich geschrieben!
Zitat:

Ich möchte aber diese Funktion nicht auf WordWrap erweitern deshalb muss der String vorbereitet werden.
Das Problem ist ganz einfach.
Ich habe mehr als 50 Anwendungen mit meiner Library geschrieben und möchte jetzt nicht nur wegen dieser einzigen Konstellation
die Library anpassen und alle Programme daraufhin umschreiben müssen.

Wenn ich den String vorbereite sollte es auch so ohne jegliche Änderung meiner Funktion möglich sein.

gruss

TiGü 20. Nov 2018 14:36

AW: Wordwrap umbruch
 
Du versuchst also wieder auf Biegen und Brechen irgendetwas zu nutzen, weil du denkst, es passt zu deinem Problem und lässt andere Lösungsvorschläge gar nicht zu?

Erstens mal ist das temporäre Erzeugung von einen VCL-TLabel in der von dir gezeigten Methode Quatsch.
Das Label weiß nichts über den Kontext bzw. Parent, auf den du später selber mit der Hand per GDI+ zeichnest.
So hat das Label überhaupt keine Informationen über die verwendete Schrift und nimmt irgendeinen Default für die Font-Property an (wahrscheinlich Tahoma in Größe 8).

Des Weiteren veränderst du so den FAudioSessionInfo.DisplayName.
Das sind aber deine Originaldaten und das ganze umbrechen und kürzen sollte erst an der Stelle erfolgen, wo du deine Textausgabe machst.

Der von mir gezeigte Quelltext ließe sich problemlos auf dein Problem anwenden.
Probiere das Konsolenprojekt doch aus und spiele ein bisschen mit den Funktionsargumenten von WrapText.

EWeiss 20. Nov 2018 14:51

AW: Wordwrap umbruch
 
Zitat:

und lässt andere Lösungsvorschläge gar nicht zu?
Sorry unser ureigenes Problem.. wenn es nicht nach deinen willen geht dann bin ich wieder der böse.
Zitat:

Biegen und Brechen irgendetwas zu nutzen
Richtig wenn es funktioniert ist es ausreichend für mich, es muss aber nicht zwangsweise dein Vorschlag sein.
Zitat:

Erstens mal ist das temporäre Erzeugung von einen VCL-TLabel in der von dir gezeigten Methode Quatsch.
Das Label weiß nichts über den Kontext bzw. Parent, auf den du später selber mit der Hand per GDI+ zeichnest.
So hat das Label überhaupt keine Informationen über die verwendete Schrift und nimmt irgendeinen Default für die Font-Property an (wahrscheinlich Tahoma in Größe 8).
Es ist ja so ein Quatsch das es nicht funktioniert so wie du im Anhang sehen kannst solange wie 2 Zeilen nicht überschritten werden.

Zitat:

Des Weiteren veränderst du so den FAudioSessionInfo.DisplayName.
Das ist der sinn der ganzen Sache.
Zitat:

Das sind aber deine Originaldaten und das ganze umbrechen und kürzen sollte erst an der Stelle erfolgen, wo du deine Textausgabe machst.
Wird an der stelle erledigt die ich für richtig halte.
Da du keine Ahnung hast welche nachfolgende Probleme dadurch entstehen können.
Zum Beispiel meine ganzen anderen Programme deshalb umzuschreiben.
Zitat:

Der von mir gezeigte Quelltext ließe sich problemlos auf dein Problem anwenden.
Probiere das Konsolenprojekt doch aus und spiele ein bisschen mit den Funktionsargumenten von WrapText.
Danke Nein!
Ich werde den String auf meine weise Splitten und weiter bearbeiten.
Aber vielleicht hilft dein Vorschlag jemand andern.

Habe ja schon 3 Beiträge vorher geschrieben das ich das mit dem Label verwerfen werde da es nicht den zweck erfüllt den ich mir erhofft habe.

Zitat:

Werde den String splitten und die länge sowie den Umbruch von Hand berechnen.
Der Label hat sich dann erledigt.
Oder die vorgeschlagene Variante von @Delphi.Narium versuchen.

OK!
Danke Thema ist erledigt werde die für mich praktikable Lösung erarbeiten ohne meine Library zu verändern.
Mit dem Label geht es nicht wenn mehr als 2 Zeilen ins Spiel kommen und das war meine Frage.

gruss

KodeZwerg 20. Nov 2018 15:38

AW: Wordwrap umbruch
 
Hey, schaut doch supi aus was Du da gemacht hast, anscheinend ist es Dir gelungen, gratuliere! (bezieht sich auf dein bild)

Ich hätte jetzt nur noch vorschlagen können, wenn Du zwei Zeilen willst, setz zwei OnTop align labels in ein Panel.

EWeiss 20. Nov 2018 15:45

AW: Wordwrap umbruch
 
Zitat:

Zitat von KodeZwerg (Beitrag 1418547)
Hey, schaut doch supi aus was Du da gemacht hast, anscheinend ist es Dir gelungen, gratuliere! (bezieht sich auf dein bild)
Ich hätte jetzt nur noch vorschlagen können, wenn Du zwei Zeilen willst, setz zwei OnTop align labels in ein Panel.

Es funktionierte alles solange der Umbruch sich auf 2 Zeilen beschränkt.
Danach jedoch nicht mehr aber wie gesagt werde für das Problem eine Lösung erarbeiten halt nur nicht mit Labeln.

Mit dem Font bzg. der Zuweisung welchen ich verwenden möchte inkl. dem FontSize hat er ja recht.
Nur er kann nicht behaupten das es quatsch ist denn er weis ja gar nicht welchen Font und Fontsize ich an meine Funktion weiter leite
das ist nämlich genau der Default Font eines Labels und deshalb passt es.

Zuweisung hätte ich noch addieren können das ist schon richtig war aber im Moment nicht nötig.

Danke.

gruss

EWeiss 20. Nov 2018 17:33

AW: Wordwrap umbruch
 
Nur als Nachtrag!

Habe die Funktion mit dem Label jetzt aus der AudioSessionVolume.pas rausgeschmissen und ändere den Text jetzt in der Anwendung selbst.
So ist man von der TAudioVolume unabhängig und ändert den Text dort wo es angebracht ist.

Zudem muss ich dann nichts mehr berechnen da ich das innerhalb meiner Library schon tue.
Wenn der Text länger ist wie das Control und sich kein Leerzeichen innerhalb des Textes befindet dann schicke ich einfach nur mein Flag GD_Ellipsis und fertig.

Die Anwendung muss sich dann um die Formatierung des Textes selber kümmern.

Delphi-Quellcode:
      GDIP_GetTextBound(MainClass.DeviceName, FontName, 13, bw, bh, nil, GD_TextHorzUp);

      // DeviceName
      x := x1;
      y := 41;

      ID := ID_DEVICENAME + Index;

      for i := 1 to Length(MainClass.DeviceName) do
      begin
        if MainClass.DeviceName[i] = ' ' then
        begin
          bNull := True;
          gSprSession.GD_DrawTextToCtrlEx(HSprSession, PWideChar(Trim(MainClass.DeviceName)), x, y,
            ParentWidth, bh * 2, gSprSession.GD_ARGB(255, 255, 255, 255), PWideChar(FontName), nil, 13,
            ID, GS_VISIBLE, 0, Ord(StringAlignmentCenter));
          break;
        end;
      end;

      if not bNull then
      begin
        if (bw > ParentWidth) then
          gSprSession.GD_DrawTextToCtrlEx(HSprSession, PWideChar(Trim(MainClass.DeviceName)), x + 2, y,
            ParentWidth, bh, gSprSession.GD_ARGB(255, 255, 255, 255), PWideChar(FontName), nil, 13,
            ID, GS_VISIBLE, 0, GD_Ellipsis) // ***** das war's schon
        else
        gSprSession.GD_DrawTextToCtrlEx(HSprSession, PWideChar(Trim(MainClass.DeviceName)), x, y,
          ParentWidth, bh * 2, gSprSession.GD_ARGB(255, 255, 255, 255), PWideChar(FontName), nil, 13,
          ID, GS_VISIBLE, 0, Ord(StringAlignmentCenter));
      end;

      gSprSession.GD_SetObjectUse3Dshadow(ID, 1.1, true);
      gSprSession.GD_SetObjectLinked(ID, LinkedID);
      gSprSession.GD_SetObjectLocked(ID, true);
Es löst zwar nicht das Problem mit den 3 Zeilen macht mich aber unabhängig von TAudioVolume.

gruss

EWeiss 20. Nov 2018 21:50

AW: Wordwrap umbruch
 
Ok funktioniert jetzt..
Musste leider doch eingriff in meine Library nehmen um das Problem beheben zu können.
Es waren keine zusätzlichen Berechnungen nötig.

Hat aber keinen großen Einfluss auf meine anderen Anwendungen weil ich letztendlich nur eine Konstante "GD_CenterAndEllipsis" addiert habe.
Ich zentriere den Text innerhalb des Control und addiere Ellipsis wenn nötig.
Delphi-Quellcode:
      for i := 1 to Length(MainClass.DeviceName) do
      begin
        if MainClass.DeviceName[i] = ' ' then
        begin
          bNull := True;
          gSprSession.GD_DrawTextToCtrlEx(HSprSession, PWideChar(Trim(MainClass.DeviceName)), x, y,
            ParentWidth, bh * 2, gSprSession.GD_ARGB(255, 255, 255, 255), PWideChar(FontName), nil, 13,
            ID, GS_VISIBLE, 0, GD_CenterAndEllipsis);
          break;
        end;
      end;
gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:49 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