Recent

Author Topic: Multiline text on dbGrid  (Read 6865 times)

NotNickolay

  • Newbie
  • Posts: 1
Multiline text on dbGrid
« on: January 27, 2017, 03:22:21 pm »
Hi Folks, I've create a small application that reads strings from a text field of mysql, so this string can return 1 char to N chars (talking about the text length), after some searches on Google, I finally found a way, that makes the dbGrid show the right text instead of a (memo) advice, but the code doesn't create the LineEndings based on the cell width.

So my question is, how can I update the cell heigth of the cells (or lines if you prefer) of my grid, so when I have a big string this line can be higher, and stay with the default size when is a small string


msch

  • New Member
  • *
  • Posts: 10
Re: Multiline text on dbGrid
« Reply #1 on: January 03, 2022, 01:09:18 am »

Well as long as we can not override the procedure "DefaultDrawCell" of the TCustomGrid, there is no clean way to build a Lazarus DBGrid-Component with MultiLine Components inserted.
 

wp

  • Hero Member
  • *****
  • Posts: 9575
Re: Multiline text on dbGrid
« Reply #2 on: January 03, 2022, 01:42:29 am »
The LCL grids are much superior to Delphi's grids. For specific painting requirements it usually is enough to write a handler for the OnPrepareCanvas event instead of redrawing the entire cell. OnPrepareCell is called immediately before the cell is painted and you have a last chance to modify drawing parameters, for example switching the Canvas.TextStyle to multiline mode:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.DBGrid1PrepareCanvas(sender: TObject; DataCol: Integer;
  2.   Column: TColumn; AState: TGridDrawState);
  3. var
  4.   ts: TTextStyle;
  5. begin
  6.   if Column.Field.DataType = ftMemo then
  7.   begin
  8.     ts := DBGrid1.Canvas.TextStyle;
  9.     ts.SingleLine := false;
  10.     ts.Wordbreak := true;
  11.     DBGrid1.Canvas.TextStyle := ts;
  12.   end;
  13. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

msch

  • New Member
  • *
  • Posts: 10
Re: Multiline text on dbGrid
« Reply #3 on: January 04, 2022, 10:35:22 pm »

Hi thanks for your code snipped.   Let's make a minimal component and look whats gonna happen

Code: Pascal  [Select][+][-]
  1. unit UNIT_DB_TSDBGrid;
  2.  
  3. interface
  4. uses  DBGrids, DB, DBCtrls,  Windows, Messages, SysUtils, Classes, CommDlg, ShellAPI, LCLType,
  5.          ShlObj, Registry, ComCtrls, Controls, StdCtrls, ExtCtrls, Grids, Graphics,  Menus, Dialogs;
  6. type
  7.  
  8.   TSDBGrid = class(TDBGrid)
  9.   private
  10.         constructor Create(AOwner: TComponent);
  11.         destructor Destroy;
  12.   public
  13.         procedure DoPrepareCanvas( aCol, aRow: Integer; aState: TGridDrawState);
  14.   end;
  15.  
  16. implementation
  17.  
  18. constructor TSDBGrid.Create(AOwner: TComponent);
  19. begin
  20.   inherited Create(AOwner);
  21. end;
  22.  
  23. destructor TSDBGrid.Destroy;
  24. begin
  25.    inherited Destroy;
  26. end;
  27.  
  28. procedure TSDBGrid.DoPrepareCanvas(aCol, aRow: Integer;   aState: TGridDrawState);
  29. var
  30.   DataCol    : Integer;
  31.   IsSelected : boolean;
  32.   ts         : TTextStyle;
  33. begin
  34.   { non fixed Rows}
  35.   if (ARow>=FixedRows) then
  36.   begin
  37.     if not DefaultDrawing then begin
  38.       GetSelectedState(aState, IsSelected);
  39.       if IsSelected then begin
  40.         Canvas.Brush.Color := SelectedColor;
  41.         Canvas.Font.Color := clHighlightText;
  42.       end;
  43.     end;
  44.     if Assigned(OnPrepareCanvas) then begin
  45.       DataCol := ColumnIndexFromGridColumn(aCol);
  46.       if DataCol>=0 then
  47.         OnPrepareCanvas(Self, DataCol, TColumn(Columns[DataCol]), aState);
  48.     end;
  49.     if DataCol>=0 then
  50.     //    if Columns[DataCol].Field.DataType = ftMemo then   // in comment for demonstration
  51.       begin
  52.         ts := Canvas.TextStyle;
  53.         ts.SingleLine := false;
  54.         ts.Wordbreak := true;
  55.         Canvas.TextStyle := ts;
  56.       end;
  57.   end;
  58. end;
  59.  

First the code snipped works - trés chic -

Now whats about the "ftmemo" - have a look into the attchment.


wp

  • Hero Member
  • *****
  • Posts: 9575
Re: Multiline text on dbGrid
« Reply #4 on: January 04, 2022, 11:13:19 pm »
You must provide a handler for the memo field's OnGetText event. Here you can pass the text to be displayed by the grid:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.MemoGetTextHandler(Sender: TField; var aText: string;
  2.   DisplayText: Boolean);
  3. begin
  4.   if DisplayText and (Sender.DataType = ftMemo) then
  5.     aText := Sender.AsString;
  6. end;

Unless you work with persistent fields (where you can assign the handler in the object inspector) you must search the memo field(s) and assign the event handler manually:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.QryArticlesAfterOpen(DataSet: TDataSet);
  2. var
  3.   f: TField;
  4. begin
  5.   for f in Dataset.Fields do
  6.     if f.DataType = ftMemo then
  7.       f.OnGetText := @MemoGetTextHandler;
  8. end;

« Last Edit: January 04, 2022, 11:19:30 pm by wp »
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

egsuh

  • Hero Member
  • *****
  • Posts: 924
Re: Multiline text on dbGrid
« Reply #5 on: January 05, 2022, 04:46:25 am »
Hi wp,
Is it possible to extend display lines --- if two lines, the hight of that row is adjusted to show two lines ---- within OnPrepareCanvas?

I did this in different way, but if there are simpler ways, I'd like to use it.

egsuh

  • Hero Member
  • *****
  • Posts: 924
Re: Multiline text on dbGrid
« Reply #6 on: January 05, 2022, 09:12:40 am »
Quote
Is it possible to extend display lines --- if two lines, the hight of that row is adjusted to show two lines ---- within OnPrepareCanvas?

I did this in different way, but if there are simpler ways, I'd like to use it.

Forget this. I'm using this already^^

msch

  • New Member
  • *
  • Posts: 10
Re: Multiline text on dbGrid
« Reply #7 on: January 05, 2022, 12:20:04 pm »

I see: To use the  handler for the memo field's OnGetText event is an elgant solution for the Form. You run the code once your're open the query. The advantage seems to me that you may have several grids and no one has the [memo] Display-Text.

Well I hesitate to use this in a derived component due to the possibility to have more then one Grid on the form. In this case every Grid would have it's handler code and maybe one Grid should have the [memo] displayed and the other one not. In this szenario one Grid would decide for all other grids too.





wp

  • Hero Member
  • *****
  • Posts: 9575
Re: Multiline text on dbGrid
« Reply #8 on: January 05, 2022, 07:14:38 pm »
I forgot, there's an even simpler possibility: Check the grid option dgDisplayMemoText to show the memo as full text rather than '(Memo)' only.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

msch

  • New Member
  • *
  • Posts: 10
Re: Multiline text on dbGrid
« Reply #9 on: January 05, 2022, 11:19:30 pm »


The orignal Lazarus DBGrid shows with dgDisplayMemoText the memo text - but without carriage returns in the result - simply a long line.  So the combination of the snipped and the option made the run for the DBGrid with MultiLine Elements in the Cell.

Currently there are some Grid-Components for Delphi with Multiline but for Lazarus I found none.

Cool  8)   Thanks a lot !

 

TinyPortal © 2005-2018