Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Probleme mit TextWidth im String Grid (https://www.delphipraxis.net/176398-probleme-mit-textwidth-im-string-grid.html)

Andidreas 2. Sep 2013 13:21

Delphi-Version: 5

Probleme mit TextWidth im String Grid
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich habe mir eine Funktion gebastelt mit der ich die Spaltenbreiten in einem StringGrid automatisch ermittle:

Delphi-Quellcode:
procedure prTStringGridAutoFit(strgrid : TStringGrid);

var
iMaxTextLength : Integer;
iCol, iRow     : Integer;

begin

  //=== Auto Fit Columns =======================================================
  For iCol := 0 to (strGrid.ColCount -1) Do
  Begin
    iMaxTextLength := 0;
    For iRow := 0 To (strGrid.RowCount - 1 ) Do
    Begin
      If strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]) > iMaxTextLength Then
      Begin
        iMaxTextLength := strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]);
      End;
    End;
    strGrid.ColWidths[iCol] := iMaxTextLength + 25;
  End;
  //============================================================================

end;
In meinem aktuelle StringGrid habe ich unterschiedliche Schriftgrößen und Formattierungen (Fett, usw.)...
An was Orientiert sich denn die TextWidth Funktion? Nimmt es zur Berrechnung der Text Länge zufällig die Größte Schriftgröße?

Weil in meinem aktuellen Fall habe ich das Problem das ich in der ersten Spalte in kleinerer Schrift lange Texte hab und darunter einen kurzen Text mit einer größeren Schriftgröße und meine Spaltebreite absolut nicht zu den Text längen passt...?

DeddyH 2. Sep 2013 13:27

AW: Probleme mit TextWidth im String Grid
 
Ich fürchte, das wird nicht funktionieren. Man kann einem StringGrid nur einen Font zuweisen, will man mehrere verwenden, muss man eben selbst zeichnen. Canvas.TextWidth dürfte sich aber lediglich auf den dem Grid-Canvas aktuell zugewiesenen Font orientieren.

Andidreas 2. Sep 2013 15:03

AW: Probleme mit TextWidth im String Grid
 
Vielleicht hab ich mich falsch ausgedrückt...

Ich verwende nur eine Art von Font, diese aber in unterschiedlichen Schriftgrößen!

Deshalb meine Frage ob sich TextWidth an der größten Schriftgröße orientiert?

DeddyH 2. Sep 2013 15:06

AW: Probleme mit TextWidth im String Grid
 
Du zeichnest aber doch selber im OnDrawCell, oder wie bekommst Du die unterschiedlichen Schriftgrößen hin? Und dazu setzt Du dann StringGrid.Canvas.Font.Size. TextWidth wird dann aus dem aktuell zugewiesenen Font errechnet und nicht aus dem, den die Zeichenfläche zwischenzeitlich mal hatte.

Blup 2. Sep 2013 16:41

AW: Probleme mit TextWidth im String Grid
 
Also muss die Zuweisung der Schrift-Attribute vor der Größenbestimmung genauso erfolgen, wie vor dem Zeichnen.
Am besten in einer Prozedur kapseln, die in beiden Fällen pro Spalte oder Zelle aufgerufen wird.

Perlsau 2. Sep 2013 18:52

AW: Probleme mit TextWidth im String Grid
 
Zitat:

Zitat von Blup (Beitrag 1226898)
Also muss die Zuweisung der Schrift-Attribute vor der Größenbestimmung genauso erfolgen, wie vor dem Zeichnen.
Am besten in einer Prozedur kapseln, die in beiden Fällen pro Spalte oder Zelle aufgerufen wird.

Wenn du die Breite der Spalte mit den beiden unterschiedlichen Fontgrößen automatisch einstellen willst, vergleichst du die beiden TextWidth-Ergebnisse der beiden Zeilen in deiner Zelle und wählst die größere als Richtschnur aus. Da du diese Zelle offenbar im OnDraw selber zeichnest, mußt du dort auch die Zellbreite berechnen bzw. von dort aus eine Berechnungsmethode aufrufen.

Furtbichler 3. Sep 2013 07:16

AW: Probleme mit TextWidth im String Grid
 
Du kannst ganz einfach im OnDrawCell-Event die Spaltenbreite anpassen: Einfach vor dem Zeichnen prüfen, ob es reinpassen würde. Wenn nicht: Breite setzen.

Hat nur den Nachteil, das es beim Scrollen zuppelt, wenn dann plötzlich ein breiter Text erscheint.

Perlsau 3. Sep 2013 07:19

AW: Probleme mit TextWidth im String Grid
 
Zitat:

Zitat von Furtbichler (Beitrag 1226948)
Hat nur den Nachteil, das es beim Scrollen zuppelt, wenn dann plötzlich ein breiter Text erscheint.

Das Zuppeln läßt sich vermeiden, wenn man pro Spalte den breitesten Text ermittelt und die jeweilige Spaltenbreite danach setzt.

DeddyH 3. Sep 2013 07:25

AW: Probleme mit TextWidth im String Grid
 
Da sowohl Cols als auch Rows von TStringGrid TStrings sind, könnte man auch theoretisch den jeweiligen Font in dessen Objects-Eigenschaft ablegen. Damit kann man dann dynamisch breiter/schmaler schalten oder die optimale Spaltenbreite berechnen.

Andidreas 3. Sep 2013 08:22

AW: Probleme mit TextWidth im String Grid
 
Vielen Dank für die vielen Antworten...

Zitat:

Zitat von Perlsau (Beitrag 1226950)
Zitat:

Zitat von Furtbichler (Beitrag 1226948)
Hat nur den Nachteil, das es beim Scrollen zuppelt, wenn dann plötzlich ein breiter Text erscheint.

Das Zuppeln läßt sich vermeiden, wenn man pro Spalte den breitesten Text ermittelt und die jeweilige Spaltenbreite danach setzt.

Jupp, das macht meine Prozedur ja schon ;-)

Ich versteh was Ihr meint und ich mein ich hab das auch schon so umgesetzt... Korrigiert mich wenn ich falsch liege...

Also hier mein Ablauf:
1. Daten in StringGrid schreiben
2. Aufruf der Routine aus meinem ersten Beitrag um die Spalten Breite festzulegen

So sollte ich doch eigentlich die maximale länge erhalten und die Spalten Breite optimal anpassen können?

Anbei noch der Source aus dem OnDrawCell:
Delphi-Quellcode:
procedure Teancheck_eanscan_form.strgrid_eancheckDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);

var
fntSize      : Integer;
s            : String;
fntAlignment : TAlignment;

begin


  //=== Format Settings for Current Scan =======================================
  //Headers
  fntAlignment := taLeftJustify;
  If ARow In [0,1,2,4,5,7,8] Then
  Begin
    strgrid_eancheck.Canvas.Brush.Color := $00A2FBF7;
    strgrid_eancheck.Canvas.Font.Color    := clBlack;
    strgrid_eancheck.Canvas.Font.Size  := 9;
    strgrid_eancheck.Canvas.Font.Name  := 'Trebuchet MS';
    strgrid_eancheck.Canvas.Font.Style := strgrid_eancheck.Canvas.Font.Style + [fsBold];
  End;
  //Data
  If ARow In [3,6,9] Then
  Begin
    strgrid_eancheck.Canvas.Brush.Color := $00CCFDFB;
    strgrid_eancheck.Canvas.Font.Color    := clBlack;
    strgrid_eancheck.Canvas.Font.Size  := 11;
    strgrid_eancheck.Canvas.Font.Name  := 'Trebuchet MS';
    strgrid_eancheck.Canvas.Font.Style := strgrid_eancheck.Canvas.Font.Style + [fsBold];
  End;
  //============================================================================



  //=== Format Settings for Previous Scan ======================================
  //Headers
  fntAlignment := taLeftJustify;
  If ARow In [12,13,14,16,17,19,20] Then
  Begin
    strgrid_eancheck.Canvas.Brush.Color := $00D8D8D8;
    strgrid_eancheck.Canvas.Font.Color    := clBlack;
    strgrid_eancheck.Canvas.Font.Size  := 9;
    strgrid_eancheck.Canvas.Font.Name  := 'Trebuchet MS';
    strgrid_eancheck.Canvas.Font.Style := strgrid_eancheck.Canvas.Font.Style + [fsBold];
  End;
  //Data
  If ARow In [15,18,21] Then
  Begin
    strgrid_eancheck.Canvas.Brush.Color := $00E5E5E5;
    strgrid_eancheck.Canvas.Font.Color    := clBlack;
    strgrid_eancheck.Canvas.Font.Size  := 11;
    strgrid_eancheck.Canvas.Font.Name  := 'Trebuchet MS';
    strgrid_eancheck.Canvas.Font.Style := strgrid_eancheck.Canvas.Font.Style + [fsBold];
  End;
  //============================================================================



  //=== Format Settings for selected Cell ======================================
  fntAlignment := taLeftJustify;
  If ARow In [0,1,2,4,5,7,8,12,13,14,16,17,19,20] Then fntSize := 9 Else fntSize := 10;
  If (gdSelected In State) Then
  Begin
    strgrid_eancheck.canvas.Brush.Color := clHighlight;
    strgrid_eancheck.Canvas.Font.Color    := clWhite;
    strgrid_eancheck.Canvas.Font.Size  := fntSize;
    strgrid_eancheck.Canvas.Font.Name  := 'Trebuchet MS';
    strgrid_eancheck.Canvas.Font.Style := strgrid_eancheck.Canvas.Font.Style + [fsBold];
  End;
  //============================================================================



  //=== Drawing ================================================================
  strgrid_eancheck.canvas.FillRect(Rect);
  s := strgrid_eancheck.Cells[ACol, ARow];
  strgrid_eancheck.canvas.FillRect(Rect);
  If fntAlignment = taLeftJustify Then DrawText(strgrid_eancheck.Canvas.Handle, PChar(s), Length(s), Rect, DT_SINGLELINE or DT_LEFT or DT_VCENTER);
  If fntAlignment = taRightJustify Then DrawText(strgrid_eancheck.canvas.Handle, PChar(s), Length(s), Rect, DT_SINGLELINE or DT_RIGHT or DT_VCENTER);
  If fntAlignment = taCenter Then DrawText(strgrid_eancheck.canvas.Handle, PChar(s), Length(s), Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
  //============================================================================

end;

DeddyH 3. Sep 2013 08:27

AW: Probleme mit TextWidth im String Grid
 
Und wo merkst Du Dir nun die maximale Breite je Spalte? Hab ich das übersehen?

Andidreas 3. Sep 2013 08:31

AW: Probleme mit TextWidth im String Grid
 
In der Variablen iMaxTextLength
Ich geh ja mein StringGrid Spaltenweise durch und pro Spalte merke ich mir den längsten Wert...

DeddyH 3. Sep 2013 08:35

AW: Probleme mit TextWidth im String Grid
 
Ja wann denn? Ich habe den Code gerade 4 mal durchgesehen, kann die Variable aber nirgends entdecken.

[edit] BTW: Ich würde den DRY-Code mal ein wenig entschlacken. [/edit]

Andidreas 3. Sep 2013 08:40

AW: Probleme mit TextWidth im String Grid
 
Hier ist nochmal der Source aus meinem ersten Beitrage:

Delphi-Quellcode:
procedure prTStringGridAutoFit(strgrid : TStringGrid);

var
iMaxTextLength : Integer;
iCol, iRow     : Integer;

begin

  //=== Auto Fit Columns =======================================================
  For iCol := 0 to (strGrid.ColCount -1) Do
  Begin
    iMaxTextLength := 0;
    For iRow := 0 To (strGrid.RowCount - 1 ) Do
    Begin
      If strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]) > iMaxTextLength Then
      Begin
        iMaxTextLength := strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]);
      End;
    End;
    strGrid.ColWidths[iCol] := iMaxTextLength + 25;
  End;
  //============================================================================

end;
Diese Routine ruf ich auf nachdem ich mein StringGrid befüllt habe... (also Schritt 2)...

DeddyH 3. Sep 2013 08:43

AW: Probleme mit TextWidth im String Grid
 
Nach dem Befüllen nützt es Dir doch nichts mehr, das sagen wir doch die ganze Zeit.

Andidreas 3. Sep 2013 08:46

AW: Probleme mit TextWidth im String Grid
 
Ok, das war ja meine Frage bzw. das was ich nicht ganz verstanden hab... Also ob mein Ablauf im Moment schon dem entspricht was ich mache...

D.h. ich muss mir die Maximal Länge im OnCellDraw merken und am Schluss vom befüllen über diesen Maximal Wert die Spaltenbreite anpassen?

Perlsau 3. Sep 2013 08:50

AW: Probleme mit TextWidth im String Grid
 
Also ich setz die Spaltenbreiten bereits beim Befüllen und ganz ohne OnCellDraw, wie man in diesem Testprojekt sehen kann:
Delphi-Quellcode:
// ********** BEFÜLLEN DES GRIDS MIT ORT-INFORMATIONEN AUS ORT-OBJEKTEN **************************************************************
Procedure TFormMain.GridFill_Orte;
Var
  Liste,
  SepList : TStrings;
  Land   : String;
  Breit,
  i,z,k,x : Integer;
  Start,
  Ende   : TDateTime;
  Sek    : Extended;
  Breite : Array[0..ColMax] OF Integer; // Array für die Spaltenbreiten

begin
  Start := Now;
  Land := Combo_Land.Text;

  Label_Orte_Anzahl.Caption := 'Bitte warten ...';
  Label_Orte_Dauer.Caption := 'Orts-Daten werden geladen ...';
  Forms.Application.ProcessMessages;

  Liste  := TStringList.Create;
  SepList := TStringList.Create;
  SepList.Delimiter := ';';
  SepList.StrictDelimiter := True;

  Try
    Einrichten_Orte;
    StrGrid_Orte.Visible := False;
    IF HC.GetOrteFromLand(Land,Liste) THEN
    BEGIN
      z := Liste.Count;
      IF z > 0 THEN
      BEGIN
        FOR i := 0 TO StrGrid_Orte.ColCount -1 DO Breite[i] := StrGrid_Orte.ColWidths[i];

        FOR i := 0 TO z-1 DO
        BEGIN
          SepList.DelimitedText := Liste[i];
          x := SepList.Count;
          IF x > 0 THEN
          FOR k := 0 TO x-1 DO
          BEGIN // Zuweisung der Zell-Inhalte und Setzen der Spaltenbreiten
            StrGrid_Orte.RowCount := i + 2;
            StrGrid_Orte.Cells[k,i+1] := SepList[k];
            Breit := StrGrid_Orte.Canvas.TextWidth(SepList[k]) + GridSpace;
            IF Breit > Breite[k] THEN Breite[k] := Breit;
          END;
        END;
      END;
    END;

  Finally
    SepList.Free;
    Liste.Free;
    Label_Orte_Anzahl.Caption := 'enthält ' + IntToStr(z)+ ' Einträge';
    Breit := 55;
    FOR i := 0 TO ColMax DO
    BEGIN
      StrGrid_Orte.ColWidths[i] := Breite[i];
      Breit := Breit + Breite[i];
    END;
    StrGrid_Orte.Visible := True;
    FormMain.Width := Breit; // Die Integer-Variable Breit ist die Summe aller Werte im Breite-Array
    StrGrid_Orte.SetFocus;

    Ende := Now;
    Sek := DateUtils.MilliSecondsBetween(Start,Ende) / 1000;
    Label_Orte_Dauer.Caption := 'Ladezeit: ' + FloatToStr(Sek) + ' sec';
  End;
end;

Blup 3. Sep 2013 08:52

AW: Probleme mit TextWidth im String Grid
 
Zitat:

Zitat von Andidreas (Beitrag 1226960)
Ich versteh was Ihr meint und ich mein ich hab das auch schon so umgesetzt... Korrigiert mich wenn ich falsch liege...

Offensichtlich eher nicht. Um deine Struktur beizubehalten:
Delphi-Quellcode:
procedure DoOnDrawCell(...);
begin
  SetzeFontEigenschaften(ACol, ARow);
  {Zeichnen...}
end;
 
procedure prTStringGridAutoFit(strgrid : TStringGrid);

var
iMaxTextLength : Integer;
iCol, iRow : Integer;

begin

  //=== Auto Fit Columns =======================================================
  For iCol := 0 to (strGrid.ColCount -1) Do
  Begin
    iMaxTextLength := 0;
    For iRow := 0 To (strGrid.RowCount - 1 ) Do
    Begin

      SetzeFontEigenschaften(iCol, iRow);

      If strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]) > iMaxTextLength Then
      Begin
        iMaxTextLength := strGrid.Canvas.TextWidth(strGrid.Cells[iCol, iRow]);
      End;
    End;
    strGrid.ColWidths[iCol] := iMaxTextLength + 25;
  End;
  //============================================================================

end;

DeddyH 3. Sep 2013 08:54

AW: Probleme mit TextWidth im String Grid
 
Das entspricht prinzipiell genau dem Gesagten. Und das kann man auch im OnDrawCell machen, und zwar zweckmäßigerweise vor oder hinter den DrawText-Aufrufen, da ist der aktuelle Font und der darzustellende Text bekannt.

Blup 3. Sep 2013 08:55

AW: Probleme mit TextWidth im String Grid
 
Beim Scrollen führt das zu dem beschriebenen Effekt, das sich plötzlich die Breite ändert...

DeddyH 3. Sep 2013 08:57

AW: Probleme mit TextWidth im String Grid
 
Auch wieder wahr.

[edit] Wenn man keinen InplaceEditor braucht, könnte man auch darüber nachdenken, das StringGrid gegen eine ListView mit ViewStyle vsReport auszutauschen. Die beherrscht das AutoFit schon von sich aus. [/edit]


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