Forum > LCL
[SOLVED] How to force Event StringGrid.OnPrepareCanvas to be called for all Rows
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