Forum > LCL

[SOLVED] How to force Event StringGrid.OnPrepareCanvas to be called for all Rows

(1/2) > >>

Hartmut:
My program has a StringGrid which shall display the names of several fonts in column 2 and a demo-text using this font in column 6 (see attached screenshot). To manage this, I use this Event:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---const X_Name   = 2; {column for Font-Name}      X_Demo   = 6; {column for Demo-Text}      max_width: integer = 0; {max. width for Demo-Text column} procedure TForm1.SG1PrepareCanvas(Sender: TObject; aCol, aRow: integer;                                  aState: TGridDrawState);   var w: integer;   begin   if aRow < 1 then exit;       {if title row}   if aCol <> X_Demo then exit; {if not column for Demo-Text}    SG1.Canvas.Font.Name:=SG1.Cells[X_Name,aRow]; {set font for column 'X_Demo'}    w:=SG1.Canvas.TextWidth(SG1.Cells[X_Demo,aRow]); {compute width of demo-text}   if w > max_width then max_width:=w;              {store max. value}   end;
The problem is: when I call SG1.AutoSizeColumns to set the width for all columns, then the width for column 6 (the demo-text) is wrong (see screenshot). I assume this is, because this procedure is not usable, if a column uses different fonts. So I think, I must compute the maximum width for column 6 by myself. But the problem is, that above Event is at the beginning only called for the 1st page of the StringGrid. What I need is, that this Event is called for *all* Rows at once. Is this possible? How?

I use Lazarus 2.0.10 with FPC 3.2.0. Thanks in advance.

wp:

--- Quote from: Hartmut on December 02, 2023, 11:42:56 am ---The problem is: when I call SG1.AutoSizeColumns to set the width for all columns, then the width for column 6 (the demo-text) is wrong (see screenshot).

--- End quote ---
This reads as if OnPrepareCanvas is not executed when AutoSizeColumns is running, and looking at the source in TCustomStringGrid.AutoAdjustColumn, I see that, in fact, this is what is happening.

Please try this:

* Open grids.pas (in folder lcl of the Lazarus installation), and find the procedure TCustomStringGrid.AutoAdjustColumn(...).
* After the final "end" of the block "if (C<>nil)...end else begin...end;" and before the block "if (i=0) and (FixedRows > 0) and (C <> nil) then..." insert the following code
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---...     if C<>nil then begin        if i<FixedRows then          tmpCanvas.Font := C.Title.Font        else          tmpCanvas.Font := C.Font;      end else begin        if i<FixedRows then          tmpCanvas.Font := TitleFont        else          tmpCanvas.Font := Font;      end;       if Assigned(FOnPrepareCanvas) then           // <--- ADDED        FOnPrepareCanvas(self, aCol, i, []);       // <--- ADDED       if (i=0) and (FixedRows>0) and (C<>nil) then        aText := C.Title.Caption      else        aText := Cells[aCol, i];   ...
This should fix most of the issue. A discrepancy will remain when your OnPrepareCanvas switches to bold or italic in some combinations of the State parameter because the modified routine does not transfer a State parameter to OnPreparCanvas.

Hartmut:
Dear wp, hello again. Thank you for that suggestion. I tried it and it works. Congratulations! But I considerable hesitate to edit/change the LCL for a long list of reasons. And you wrote, that there will be problems with bold and italics, which I want to expand in the future. So I'm hoping for another solution which needs no changes to the LCL.

My imagination is a separate procedure, which calls Event 'SG1PrepareCanvas' in a loop for all Rows and computes the maximum width for the demo-text column. But this should be in a way or "context", that the assignment of all the fonts, which is done in the Event for column 6 (Demo-Text), can be "remembered" later, when the StringGrid is scrolled, so that this time-consuming task is not computed twice for many fonts. How could something like that be realized?

paweld:
sample in attachment

wp:

--- Quote from: Hartmut on December 02, 2023, 01:52:23 pm ---Dear wp, hello again. Thank you for that suggestion. I tried it and it works. Congratulations! But I considerable hesitate to edit/change the LCL for a long list of reasons.

--- End quote ---
Of course. Do you think that we should have this change in the LCL of the next release coming after v3.0? The bold/italic uncertainty probably can be overcome by being more elaborate on the State parameter. On one side I think that having an AutoSizeColumns method at all means that it should work under all - well: most? - circumstances. On the other hand, it may add some load to the grid because OnPrepareCanvar is a user function, and nobody knows what he puts in there not knowing that it is not used for drawing only.

Navigation

[0] Message Index

[#] Next page

Go to full version