Recent

Author Topic: StringGrid question  (Read 647 times)

hedgehog

  • Full Member
  • ***
  • Posts: 111
StringGrid question
« on: May 01, 2026, 10:45:39 am »
Hi

I am using an editable StringGrid. (Lazarus 4.4 win64 Windows 10)
I don't like the fact that if you select an cbsEllipsis editor, the string  moves 8 pixels to the left when editing.
How can this be fixed?

This is ugly and may confuse the user.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Grids;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     StringGrid1: TStringGrid;
  16.     procedure FormCreate(Sender: TObject);
  17.     procedure StringGrid1SelectEditor(Sender: TObject; aCol, aRow: Integer;
  18.       var Editor: TWinControl);
  19.   private
  20.  
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.StringGrid1SelectEditor(Sender: TObject; aCol, aRow: Integer;
  35.   var Editor: TWinControl);
  36. begin
  37.   if aCol=2 then Editor := StringGrid1.EditorByStyle(cbsEllipsis);
  38. end;
  39.  
  40. procedure TForm1.FormCreate(Sender: TObject);
  41. begin
  42.   StringGrid1.Cells[1,1]:= 'LAZARUS';
  43.   StringGrid1.Cells[1,2]:= 'LAZARUS';
  44.   StringGrid1.Cells[2,1]:= 'LAZARUS';
  45.   StringGrid1.Cells[2,2]:= 'LAZARUS';
  46. end;
  47.  
  48. end.
« Last Edit: May 01, 2026, 11:01:59 am by hedgehog »

wp

  • Hero Member
  • *****
  • Posts: 13502
Re: StringGrid question
« Reply #1 on: May 01, 2026, 12:31:08 pm »
Following the code with the debugger I am lead into procedure TCustomGrid.EditorPos where the boundsrect of the editor is defined (local variable CellR). There is special treatment for the FButtonStringEditor which is used by the ellipsis editor. When I add here the value varCellPadding to CellR.Left the cell text does not jump to the left any more when the editor is enabled (varCellPadding is the margin around any text in the grid cells).

Code: Pascal  [Select][+][-]
  1. procedure TCustomGrid.EditorPos;
  2. ...
  3.       if FEditor=FButtonStringEditor then begin                      // at line 8863, approximately
  4.         // here we ensure that FStringEditor which is the ActiveControl in
  5.         // FButtonStringEditor get its bounds right
  6.         inc(CellR.Left, varCellPadding);   // <---- ADDED
  7.         editorBounds := CellR;
  8.         CalcEditorBounds(FStringEditor, editorBounds);
  9.         FStringEditor.BoundsRect := editorBounds;
  10.       end;  
  11. ...

I am not sure whether this fix does not have any side-effects. It is restricted to the ellipsis editor at least, damage should not be too wide-reaching... I only tested on Windows so far, more testing on gtk2/3, qt4/5/6 and cocoa is needed before I want to apply this to the Lazarus repository.

A note on your measurement of the offset to be 8 pixels. Looking at your screenshot in detail, I see that you are measuring at the outer sides of both indicator lines, which causes an error of 1 pixel, and it seems also that the indicator line is off by another pixel at the upper "LAZARUS" - therefore I think that the true offset is 6 pixels only. But... varCellPadding is the scaled distance defined as constCellPadding = 3px for 96 ppi. Therefore I'd conclude that you are working on a monitor running at 200% (i.e. 192 ppi). Is this correct? If not, I'd have a problem understanding why the correction by varCellPadding (=3, on my system) fixes the issue.
« Last Edit: May 01, 2026, 12:41:14 pm by wp »

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #2 on: May 01, 2026, 12:40:47 pm »
It works great !

wp

  • Hero Member
  • *****
  • Posts: 13502
Re: StringGrid question
« Reply #3 on: May 01, 2026, 12:42:09 pm »
What is your screen resolution? See my "note" added after initial responding.

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #4 on: May 01, 2026, 12:50:26 pm »
Hi
My current DPI= 125%

Also, in a simple editor I see a 1 pixel offset (this is, of course, a small thing, but nevertheless).

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #5 on: May 01, 2026, 02:28:37 pm »
And a simple test. I launched Ubuntu in VirtualBox: here the editable string is shifted to the right! (64 bit, Lazarus 4.6, without changes)

wp

  • Hero Member
  • *****
  • Posts: 13502
Re: StringGrid question
« Reply #6 on: May 01, 2026, 03:47:01 pm »
I'm seeing that, too. This is better:

Code: Pascal  [Select][+][-]
  1. procedure TCustomGrid.EditorPos;
  2. ...
  3.       if FEditor=FButtonStringEditor then begin
  4.         // here we ensure that FStringEditor which is the ActiveControl in
  5.         // FButtonStringEditor get its bounds right
  6.         editorBounds := CellR;
  7.         CalcEditorBounds(FStringEditor, editorBounds);
  8.         FStringEditor.BoundsRect := editorBounds;
  9.         CellR.Left := editorBounds.Left;
  10.       end;
  11. ...

This works in Windows because the shift by varCellPadding is already done in CalcEditorBounds, or, to be more specific, in the widgetset-dependent TWin32WSCustomGrid.GetEditorBoundsFromCellRect in unit Win32WSGrids, while in gtk2, qt5, qt6 and cocoa this is not done. In gtk3, there is a jump to the right without the patch, but this widgetset does not yet contain the grids interface unit. Similarly, in cocoa there is a jump upward when the ellipsis cell editor is activated; again, there is no CocoaWSGrids interface unit yet.

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #7 on: May 01, 2026, 04:46:38 pm »
I checked your solution for Windows 10, here are the results:
DPI 96 - there is no shift, great!
DPI 120 - left shift by 1 pixel
DPI 144 - left shift by 2 pixels

Is there a rounding error somewhere inside?


wp

  • Hero Member
  • *****
  • Posts: 13502
Re: StringGrid question
« Reply #8 on: May 01, 2026, 05:12:33 pm »
Ah, there is still a "constCellPadding" in Win32WSGrids - this is the unscaled margin, but it should be replaced by the dpi-scaled value, "varCellPadding". Find the unit in lcl/interfaces/win32, there are three occurrencies of "constCellPadding".
« Last Edit: May 01, 2026, 05:44:14 pm by wp »

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #9 on: May 01, 2026, 05:27:14 pm »
Oh yes, everything is fine now !

wp

  • Hero Member
  • *****
  • Posts: 13502
Re: StringGrid question
« Reply #10 on: May 02, 2026, 07:08:26 pm »
I am not sure whether my fix can be added to the Lazarus repository as such because the inplace editors in all widgetsets have some kind of issue, and therefore, there should be a global solution. Sent a bug report: https://gitlab.com/freepascal.org/lazarus/lazarus/-/work_items/42263

hedgehog

  • Full Member
  • ***
  • Posts: 111
Re: StringGrid question
« Reply #11 on: May 03, 2026, 09:12:47 am »
Hi WP.

I noticed an irrationality when creating internal editors. They are created in the constructor, even if editing is disabled in the options.

I changed it for fun:
Code: Pascal  [Select][+][-]
  1. //....
  2. // 1
  3. function TCustomGrid.EditorByStyle(Style: TColumnButtonStyle): TWinControl;
  4. begin
  5.   case Style of
  6.     cbsEllipsis: Result := GetButtonStringEditor;
  7.     cbsButton: Result := GetButtonEditor;
  8.     cbsPicklist: Result := GetPicklistEditor;
  9.     cbsAuto:    Result := GetStringEditor;
  10.     else {cbsNone, cbsCheckboxColumn, cbsButtonColumn:}
  11.       Result := nil;
  12.   end;
  13. end;  
  14.  
  15. //....
  16. // 2
  17. function TCustomGrid.GetButtonEditor: TWinControl;
  18. begin
  19.   if FButtonEditor = nil then begin
  20.     FButtonEditor := TButtonCellEditor.Create(nil);
  21.     FButtonEditor.Name:='ButtonEditor';
  22.     FButtonEditor.Caption:='...';
  23.     FButtonEditor.Visible:=False;
  24.     FButtonEditor.Width:=25;
  25.     FButtonEditor.OnClick := @EditButtonClicked;
  26.   end;
  27.   Result:= FButtonEditor;
  28. end;
  29.  
  30. function TCustomGrid.GetStringEditor: TWinControl;
  31. begin
  32.   if FStringEditor = nil then begin
  33.     FStringEditor := TStringCellEditor.Create(nil);
  34.     FStringEditor.name :='StringEditor';
  35.     FStringEditor.Text:='';
  36.     FStringEditor.Visible:=False;
  37.     FStringEditor.Align:=alNone;
  38.     FStringEditor.BorderStyle := bsNone;
  39.   end;
  40.   Result:= FStringEditor;
  41. end;
  42.  
  43. function TCustomGrid.GetPicklistEditor: TWinControl;
  44. begin
  45.   if FPicklistEditor = nil then begin
  46.     FPicklistEditor := TPickListCellEditor.Create(nil);
  47.     FPickListEditor.Name := 'PickListEditor';
  48.     FPickListEditor.Visible := False;
  49.     FPickListEditor.AutoSize := false;
  50.   end;
  51.   Result:= FPicklistEditor;
  52. end;
  53.  
  54. function TCustomGrid.GetButtonStringEditor: TWinControl;
  55. begin
  56.   if FButtonStringEditor = nil then begin
  57.     FButtonStringEditor := TCompositeCellEditor.Create(nil);
  58.     FButtonStringEditor.Name:='ButtonTextEditor';
  59.     FButtonStringEditor.Visible:=False;
  60.     FButtonStringEditor.AddEditor(GetStringEditor, alCustom, true);
  61.     FButtonStringEditor.AddEditor(GetButtonEditor, alRight, false);
  62.   end;
  63.   Result:= FButtonStringEditor;
  64. end;
  65.  
  66. //....
  67. // 3
  68. //  and in TCustomGrid.Create it is necessary to comment out the corresponding lines
  69.  

 

TinyPortal © 2005-2018