Recent

Author Topic: [SOLVED] How change the Cell height of a StringGrid  (Read 9585 times)

douglas.cast

  • Jr. Member
  • **
  • Posts: 62
[SOLVED] How change the Cell height of a StringGrid
« on: January 19, 2017, 04:48:29 pm »
Before some research over the web I've founded some (Delphi) examples that doesn't work for me on Lazarus.

Anyone have ideia of how can I change the height of a cell to fit all the text that I have? At this moment what I got is just the default height with some some lines on the cell.

This is the code that I'm using to feed the cell content:

Code: Pascal  [Select][+][-]
  1. var
  2.   list     :TStringList;
  3.   paragraph   :String;
  4.   counter  :Integer;
  5.   i        :Integer;
  6. begin
  7.  
  8.   i := 0;
  9.  
  10.   with datamodule.song do begin
  11.     SQL.Clear;
  12.     SQL.Text:='SELECT text AS PAR FROM songs WHERE id = 1';
  13.     ExecSQL;
  14.     Open;
  15.     paragraph:=FieldByName('PAR').AsString;
  16.  
  17.     list:= TStringList.Create;
  18.  
  19.     try
  20.       list.LineBreak:=LineEnding+LineEnding; //that's the way Lazarus understan the \n\n from mysql
  21.       list.Text:=paragraph;
  22.       counter:=(list.Count)-1;
  23.  
  24.       for i := 0 to counter do
  25.       begin
  26.         stPreview.RowCount:=stPreview.RowCount+1;
  27.         stPreview.Cells[0, stPreview.RowCount-1]:=list[i];
  28.       end;
  29.     finally
  30.       FreeAndNil(list);
  31.     end;
  32.   end;
« Last Edit: January 20, 2017, 01:32:38 pm by douglas.cast »

wp

  • Hero Member
  • *****
  • Posts: 8318
Re: How change the Cell height of a StringGrid
« Reply #1 on: January 19, 2017, 05:22:58 pm »
You cannot set an individual cell height, you can only set the height of the entire row by setting StringGrid.RowHeights[rowindex].

To determine the correct row height you must iterate through all cells in the row and determine the maximum height of the text in each cell.

In order to determine the text height in a cell do this; the other procedure sets the row heights accordingly:
Code: Pascal  [Select][+][-]
  1. function GetCellHeight(AGrid: TStringGrid; ACol, ARow: Integer): Integer;
  2. var
  3.   r: Integer;
  4.   i: Integer;
  5.   L: TStringList;
  6.   h: Integer;
  7.   bmp: TBitmap;
  8. begin
  9.   bmp := TBitmap.Create;
  10.   bmp.Canvas.Font.Assign(StringGrid1.Font);
  11.  
  12.   L := TStringList.Create;
  13.   try
  14.     L.Text := StringGrid.Cells[ACol, ARow];
  15.     if L.Count > 0 then
  16.       Result := bmp.Canvas.TextHeight('Tg') * L.Count
  17.     else
  18.       Result := StringGrid.DefaultRowHeight;
  19.   finally
  20.     L.Free;
  21.     bmp.Free;
  22.   end;
  23. end;
  24.  
  25. procedure AutoRowHeight(StringGrid: TStringGrid; ARow: Integer);
  26. var
  27.   h, hmax : Integer;
  28.   col: Integer;
  29. begin
  30.   hmax := 0;
  31.   for col := 0 to StringGrid.ColCount-1 do
  32.     h := GetCellHeight(StringGrid1, col, ARow);
  33.     if h > hmax then hmax := h;
  34.   end;
  35.   StringGrid.RowHeights[ARow] := h;
  36. end;

Finally you must paint the cells with the linebreaks. It is enough to activate workbreak mode in the OnPrepareCanvas event

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1PrepareCanvas(sender: TObject; aCol, aRow: Integer;
  2.   aState: TGridDrawState);
  3. var
  4.   ts: TTextStyle;
  5. begin
  6.   ts := StringGrid1.Canvas.TextStyle;
  7.   ts.Wordbreak := true;
  8.   ts.SingleLine := false;
  9.   StringGrid1.Canvas.TextStyle := ts;
  10. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

douglas.cast

  • Jr. Member
  • **
  • Posts: 62
Re: How change the Cell height of a StringGrid
« Reply #2 on: January 19, 2017, 07:11:40 pm »
You cannot set an individual cell height, you can only set the height of the entire row by setting StringGrid.RowHeights[rowindex].

Ops, my bad, I have only one collumn, I'll set the height of one cell all the time, I'm a little bit bad with explation this days, sorry.

If I don't get it wrong, I need to return the collumn and the line to call your function, to it will be something like this: (?)

Code: Pascal  [Select][+][-]
  1. GetCellHeight(StringGridName, Collumn, Line)
  2.  
  3. GetCellHeight (stOne, 0, i);
  4.  

But nothing happens, am I  wrong in the parameters or what? If I'm not (really) wrong, I need to call this function each time I feed a cell, inside of the For loop to be more precise.

wp

  • Hero Member
  • *****
  • Posts: 8318
Re: How change the Cell height of a StringGrid
« Reply #3 on: January 19, 2017, 10:48:07 pm »
After you loaded your data into the grid you simply call AutoRowHeight (code in my previous post - it is for several columns but should work also for a single column, of course; and I hope that it compiles, I did not test it).
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

douglas.cast

  • Jr. Member
  • **
  • Posts: 62
Re: How change the Cell height of a StringGrid
« Reply #4 on: January 20, 2017, 10:13:41 am »
After you loaded your data into the grid you simply call AutoRowHeight (code in my previous post - it is for several columns but should work also for a single column, of course; and I hope that it compiles, I did not test it).

The application compiles without problems, but the code doesn't work, no visible result, cells still in the same way = /

wp

  • Hero Member
  • *****
  • Posts: 8318
Re: How change the Cell height of a StringGrid
« Reply #5 on: January 20, 2017, 12:17:50 pm »
It AutoRowHeight() there's the error that StringGrid.RowHeights[ARow] is assigned to h, it should use hmax instead.

In the attachment you find a demo which is basd on this (corrected) sample code and shows the correct behavior.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

douglas.cast

  • Jr. Member
  • **
  • Posts: 62
Re: How change the Cell height of a StringGrid
« Reply #6 on: January 20, 2017, 01:44:26 pm »
It AutoRowHeight() there's the error that StringGrid.RowHeights[ARow] is assigned to h, it should use hmax instead.

In the attachment you find a demo which is basd on this (corrected) sample code and shows the correct behavior.

'Fits like a glove' ^^

I've tryed to change that StringGri1 of the first code for AGrid and give the parameters, but I got a SigSev Error when (where) I call the function, so I gave up, since I didn't enough time in that moment to find what's wrong.

Another ideia that I had (not sure if will work) is just to count the number of LineEndings of the cell and them create a * like you have in your code, based on the font size, it should be something like: (Font) 12 * 4 (Parag), but something I've noticed is the fact that I need to run it for each line and problably will not work with multiple collumns, it's something to let quiet for now.

But once more, a big thanks very much.

The Font Size * Paragraph Count code sketch:

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TfrmMain.buttonClick(Sender: TObject);
  3. var
  4.   test  : String;
  5.   sl     : TStringList;
  6.   counter : Integer;
  7. begin
  8.   text := 'Line 1'+LineEnding+LineEnding+'Line 2'+LineEnding+'Line 3';
  9.   sl   := TStringList.Create;
  10.  
  11.   counter:=ExtractStrings([LineEnding], [' '], PChar(text), sl);
  12.  
  13.   //# the rest of the code to get the cell (line) font size then * for the counter (I didn't finish) and them transfer the result to the cell (line) Height
  14.  
  15. end;  
  16.  
  17.  

wp

  • Hero Member
  • *****
  • Posts: 8318
Re: How change the Cell height of a StringGrid
« Reply #7 on: January 20, 2017, 02:29:22 pm »
I've tryed to change that StringGri1 of the first code for AGrid and give the parameters, but I got a SigSev Error when (where) I call the function, so I gave up, since I didn't enough time in that moment to find what's wrong.
SigSegV usually occurs if an object, the grid in this case, has not been created yet. Yes, you must take the time, don't expect somebody else to solve all your programming issues. If you don't have "enough time" you should think about giving up programming, sorry to say that.

Another ideia that I had (not sure if will work) is just to count the number of LineEndings of the cell and them create a * like you have in your code, based on the font size, it should be something like: (Font) 12 * 4 (Parag), but something I've noticed is the fact that I need to run it for each line and problably will not work with multiple collumns, it's something to let quiet for now.
No problem with this approach, it should work. But I don't see why ExtractStrings should have any advantage over my method. Note also that the font *SIZE* is in points (1 pt = 1/72 inch), but you need pixels here. TFont has a member "Height" which gives the font size in pixels, but it is shown as a negative number. So, in order to get the height (in pixels) of the text you must multiply the count of lineendings (plus 1!) by -StringGrid.Font.Height (the minus sign makes the negative number positive again). You should also add a few pixels to get some margin between cellborder and cell text; grids.pas has a constant constCellPadding for that.

Here's a simple function which scans a string and counts the lineendings:
Code: Pascal  [Select][+][-]
  1. function CountLineEndings(s: String): Integer;
  2. var
  3.   i: Integer;
  4. begin
  5.   Result := 0;
  6.   i := 1;
  7.   while (i <= Length(s)) do begin
  8.     case s[i] of
  9.       #13: begin
  10.              inc(Result);
  11.              if (i < length(s)) and (s[i+1] = #10 then inc(i);
  12.            end;
  13.       #10: inc(result);
  14.     end;
  15.     inc(i);
  16.   end;
  17. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

douglas.cast

  • Jr. Member
  • **
  • Posts: 62
Re: How change the Cell height of a StringGrid
« Reply #8 on: January 20, 2017, 08:01:11 pm »
I've tryed to change that StringGri1 of the first code for AGrid and give the parameters, but I got a SigSev Error when (where) I call the function, so I gave up, since I didn't enough time in that moment to find what's wrong.
SigSegV usually occurs if an object, the grid in this case, has not been created yet. Yes, you must take the time, don't expect somebody else to solve all your programming issues. If you don't have "enough time" you should think about giving up programming, sorry to say that.

I like to run in the morning, I've taken a look at the code a few minutes earlier, I just gave up and started to run, but no problem, programming requires a good ammount of time and I know it, just one of my 'english' problems while I'm trying to express myself ^^

Once again, thank you very much

 

TinyPortal © 2005-2018