2010-12-11 20 views
7

Je veux avoir une ligne fixe en tant qu'en-tête, mais les textes sont plutôt longs, donc je voudrais augmenter la hauteur des lignes et insérer CR/LF dans le texte de la cellule. Google Googling montre cela comme une solution (et c'est la première chose que je pensais avant googling), mais il ne voit pas à travailler. Des idées?Comment mettre CR/LF dans une cellule TStringgrid?

Grid.Cells[2,3] := 'This is a sample test' + #13#10 + 'This is the second line'; 

Ce qui se passe est que la cellule contient This is a sample testThis is the second line

(Delphi 7 si elle fait une différence)

[Bounty] « Mon mauvais. En fait, j'obtenu cette réponse il y a deux ans sans vérifier et trouve maintenant que la réponse n'a pas fonctionné.Aplogies à toute personne qui a été induite en erreur.Il s'agit d'un FABOWAQ (question fréquemment posée, souvent mal répondu) .GINYF ".

Je suppose que nous cherchons à utiliser OnDrawCell, mais imaginons que nous devrions également augmenter la hauteur de la ligne de la chaîne de la chaîne qui contient la cellule.

Je vais attribuer la réponse pour le code ou un composant VCL FOSS.

[Mise à jour] doit travailler avec Delphi XE2 Starter Edition

+3

RowHeights [#] de TStringGrid ne serait pas utile? edit: AFAICS dans le code lié dans la réponse, RowHeights est utilisé dans cette mesure. –

Répondre

20

TStringGrid utilise Canvas.TextRect, qui utilise ExtTextOut, ce qui ne prend pas en charge le dessin de multiligne texte.

Vous devez dessiner vous-même dans un gestionnaire d'événements OnDrawCell avec la routine DrawText de WinAPI. Voir par exemple this answer sur la façon d'utiliser DrawText pour le texte multiligne et this recent answer sur la façon de mettre en œuvre le dessin personnalisé dans OnDrawCell:

type 
    TForm1 = class(TForm) 
    StringGrid1: TStringGrid; 
    procedure FormCreate(Sender: TObject); 
    procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    private 
    procedure FillWithRandomText(AGrid: TStringGrid); 
    procedure UpdateRowHeights(AGrid: TStringGrid); 
    end; 

procedure TForm1.FillWithRandomText(AGrid: TStringGrid); 
const 
    S = 'This is a sample'#13#10'text that contains'#13#10'multiple lines.'; 
var 
    X: Integer; 
    Y: Integer; 
begin 
    for X := AGrid.FixedCols to AGrid.ColCount - 1 do 
    for Y := AGrid.FixedRows to AGrid.RowCount - 1 do 
     AGrid.Cells[X, Y] := Copy(S, 1, 8 + Random(Length(S) - 8)); 
    UpdateRowHeights(AGrid); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FillWithRandomText(StringGrid1); 
end; 

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
begin 
    with TStringGrid(Sender) do 
    if Pos(#13#10, Cells[ACol, ARow]) > 0 then 
    begin 
     Canvas.FillRect(Rect); 
     Inc(Rect.Left, 2); 
     Inc(Rect.Top, 2); 
     DrawText(Canvas.Handle, PChar(Cells[ACol, ARow]), -1, Rect, 
     DT_NOPREFIX or DT_WORDBREAK); 
    end; 
end; 

procedure TForm1.UpdateRowHeights(AGrid: TStringGrid); 
var 
    Y: Integer; 
    MaxHeight: Integer; 
    X: Integer; 
    R: TRect; 
    TxtHeight: Integer; 
begin 
    for Y := AGrid.FixedRows to AGrid.RowCount - 1 do 
    begin 
    MaxHeight := AGrid.DefaultRowHeight - 4; 
    for X := AGrid.FixedCols to AGrid.ColCount - 1 do 
    begin 
     R := Rect(0, 0, AGrid.ColWidths[X] - 4, 0); 
     TxtHeight := DrawText(AGrid.Canvas.Handle, PChar(AGrid.Cells[X, Y]), -1, 
     R, DT_WORDBREAK or DT_CALCRECT); 
     if TxtHeight > MaxHeight then 
     MaxHeight := TxtHeight; 
    end; 
    AGrid.RowHeights[Y] := MaxHeight + 4; 
    end; 
end; 

Default StringGrid


Il existe également d'autres composants StringGrid capables de dessiner du texte multiligne . Par exemple, this one que je me suis écrit (sources de téléchargement: NLDStringGrid + NLDSparseList) avec éventuellement ce résultat:

NLDStringGrid

var 
    R: TRect; 
begin 
    NLDStringGrid1.Columns.Add; 
    NLDStringGrid1.Columns.Add; 
    NLDStringGrid1.Cells[1, 1] := 'Sample test'#13#10'Second line'; 
    NLDStringGrid1.Columns[1].MultiLine := True; 
    NLDStringGrid1.AutoRowHeights := True; 
    SetRect(R, 2, 2, 3, 3); 
    NLDStringGrid1.MergeCells(TGridRect(R), True, True); 
    NLDStringGrid1.ColWidths[2] := 40; 
    NLDStringGrid1.Cells[2, 2] := 'Sample test'#13#10'Second line'; 
end; 
+0

+1 @NGLN Je vais D/L et essayez-le maintenant. Des restrictions sur l'utilisation? – Mawg

+0

Compile échoue - ne peut pas trouver DesignEditors.dcu - probablement parce que j'utilise XE2 Starter édition? – Mawg

+0

@Mawg Possiblement, mais je ne sais pas. Avez-vous converti le paquet-fichier à XE2? Notez la ligne 'requires DesignIde'! Essayez le temps d'exécution sinon. – NGLN

5

renderer par défaut de la TStringGrid ne prend pas en charge plusieurs lignes. En définissant le TStringGrid en mode OwnerDraw (en appelant l'événement OnDrawCell), vous pouvez rendre chaque cellule de votre propre gré.

Jetez un oeil à this pour un exemple qui a aidé un utilisateur précédent.

Code de référence lié inséré:

procedure DrawSGCell(Sender : TObject; C, R : integer; Rect : TRect; 
      Style : TFontStyles; Wrap : boolean; Just : TAlignment; 
      CanEdit : boolean); 
    { draws formatted contents in string grid cell at col C, row R; 
    Style is a set of fsBold, fsItalic, fsUnderline and fsStrikeOut; 
    Wrap invokes word wrap for the cell's text; Just is taLeftJustify, 
    taRightJustify or taCenter; if CanEdit false, cell will be given 
    the background color of fixed cells; call this routine from 
    grid's DrawCell event } 
var 
    S  : string; 
    DrawRect : TRect; 
begin 
    with (Sender as tStringGrid), Canvas do begin 
    { erase earlier contents from default drawing } 
    if (R >= FixedRows) and (C >= FixedCols) and CanEdit then 
     Brush.Color:= Color 
    else 
     Brush.Color:= FixedColor; 
    FillRect(Rect); 
    { get cell contents } 
    S:= Cells[C, R]; 
    if length(S) > 0 then begin 
     case Just of 
     taLeftJustify : S:= ' ' + S; 
     taRightJustify : S:= S + ' '; 
     end; 
     { set font style } 
     Font.Style:= Style; 
     { copy of cell rectangle for text sizing } 
     DrawRect:= Rect; 
     if Wrap then begin 
     { get size of text rectangle in DrawRect, with word wrap } 
     DrawText(Handle, PChar(S), length(S), DrawRect, 
      dt_calcrect or dt_wordbreak or dt_center); 
     if (DrawRect.Bottom - DrawRect.Top) > RowHeights[R] then begin 
      { cell word-wraps; increase row height } 
      RowHeights[R]:= DrawRect.Bottom - DrawRect.Top; 
      SetGridHeight(Sender as tStringGrid); 
      end 
     else begin 
      { cell doesn't word-wrap } 
      DrawRect.Right:= Rect.Right; 
      FillRect(DrawRect); 
      case Just of 
      taLeftJustify : DrawText(Handle, PChar(S), length(S), DrawRect, 
           dt_wordbreak or dt_left); 
      taCenter  : DrawText(Handle, PChar(S), length(S), DrawRect, 
           dt_wordbreak or dt_center); 
      taRightJustify : DrawText(Handle, PChar(S), length(S), DrawRect, 
           dt_wordbreak or dt_right); 
      end; 
      end 
     end 
     else 
     { no word wrap } 
     case Just of 
      taLeftJustify : DrawText(Handle, PChar(S), length(S), DrawRect, 
          dt_singleline or dt_vcenter or dt_left); 
      taCenter  : DrawText(Handle, PChar(S), length(S), DrawRect, 
          dt_singleline or dt_vcenter or dt_center); 
      taRightJustify : DrawText(Handle, PChar(S), length(S), DrawRect, 
          dt_singleline or dt_vcenter or dt_right); 
      end; 
     { restore no font styles } 
     Font.Style:= []; 
     end; 
    end; 
end; 

Je pense que cela fonctionnera bien pour vous ...

+0

+1 Cela a l'air bien. Je vais essayer et revenir à vous.Merci – Mawg

+3

Ce code définit 'RowHeights []' dans la routine 'DrawCell'. Uglhh ... – NGLN

+1

@Mawg, c'est un exemple (en plusieurs points) de la façon dont vous ne devriez pas écrire le code (sauf qu'il fait ce que NGLN a souligné). Ma suggestion, ne l'utilisez pas ... – TLama