Recent

Author Topic: [Solved] column resize in grid-like custom component  (Read 2340 times)

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
[Solved] column resize in grid-like custom component
« on: March 19, 2018, 01:15:38 pm »
I have a custom component that is similar to a grid. I would like to resize the columns and I implemented it in some way but the resizing is not as smooth as expected.
My grid is a constituted of a list of visual components (custom viewers replaced by tpanel in the source code attached) arranged in a grid. When I resize a column a lot of lines are drawed, the resizing process is slow and visually not satisfactory.

I attached a sample of my source that can be used to reproduce this issue.
In order to check it just create a Tmygrid when you create a form:
procedure TForm1.FormCreate(Sender: TObject);
var
  mygrid: TMyGrid;
begin
  mygrid:= TMyGrid.Create(Self);
  mygrid.align:= alclient;
  mygrid.Parent:= form1;
end;

Here TMyGrid source
Code: Pascal  [Select][+][-]
  1. unit mycustomgrid;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, StdCtrls, Controls, Forms, Graphics, fgl, ExtCtrls,
  9.   LCLType, math, LCLIntf;
  10.  
  11. const
  12.   MYCELLNAME = 'MyCell';
  13.   MIN_COL_WIDTH = 10;
  14.   DEFAULT_COLUMN_SIZE = 100;
  15.   ROWCOUNT = 6;
  16.   COLCOUNT = 7;
  17.  
  18. type
  19.  
  20.   { TMyGridColumn }
  21.  
  22.   TMyGridColumn = class(TObject)
  23.   private
  24.     FWidth: Integer;
  25.     procedure SetWidth(AValue: Integer);
  26.   public
  27.     constructor Create; overload;
  28.     destructor Destroy; override;
  29.  
  30.     property Width: Integer read FWidth write SetWidth;
  31.   end;
  32.  
  33.   TMyGridColumns = specialize TFPGObjectList<TMyGridColumn>;
  34.  
  35.   { TCustomMyCell }
  36.  
  37.   TCustomMyCell = class(TCustomControl)
  38.   private
  39.     _lblFooter: TLabel;
  40.     _lblHeader: TLabel;
  41.     _myviewer: TPanel;
  42.  
  43.     function GetFooter: string;
  44.     function GetHeader: string;
  45.     procedure SetFooter(AValue: string);
  46.     procedure SetHeader(AValue: string);
  47.  
  48.     // events
  49.     procedure MouseDownCell(Sender: TObject; Button: TMouseButton;
  50.                               Shift: TShiftState; X, Y: Integer);
  51.     procedure MouseMoveCell(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  52.     procedure MouseUpCell(Sender: TObject; Button: TMouseButton;
  53.                               Shift: TShiftState; X, Y: Integer);
  54.   public
  55.     constructor Create(AOwner: TComponent); override;
  56.     destructor Destroy; override;
  57.  
  58.     property Footer: string read GetFooter write SetFooter;
  59.     property Header: string read GetHeader write SetHeader;
  60.   end;
  61.  
  62.   TMyCell = class(TCustomMyCell)
  63.  
  64.   end;
  65.  
  66.   TMyCellList = specialize TFPGObjectList<TMyCell>;
  67.  
  68.   { TMyCustomGrid }
  69.  
  70.   TMyCustomGrid = class(TCustomControl)
  71.   private
  72.     FGridLineColor: TColor;
  73.     FGridLineStyle: TPenStyle;
  74.     FGridLineWidth: Integer;
  75.  
  76.     _columns: TMyGridColumns;
  77.     _mycells: TMyCellList;
  78.     _oldCursorPos: TPoint;
  79.     _resizingcolumnID: Integer;
  80.  
  81.     procedure DrawMyCellGrid(aCol, aRow: Integer);
  82.     procedure setcellposition(const aCol, aVisibleRow: Integer; mycell: TMyCell);
  83.     procedure getcellpositionstd(const aCol, aVisibleRow: Integer; out aTop, aLeft, aHeight, aWidth: Integer);
  84.     procedure getcellposition(const aCol, aVisibleRow: Integer; out aTop, aLeft, aHeight, aWidth: Integer);
  85.     function getgridclientwidth: Integer;
  86.     function getgridclientheight: Integer;
  87.     procedure updatecolumns(const newlength: Integer);
  88.     function CreateMyCell(aCol, aRow: Integer): TMyCell;
  89.     procedure DrawAllRows;
  90.     procedure DrawRow(aRow: Integer);
  91.     procedure DestroyMyCells;
  92.     procedure CreateMyCells;
  93.     function IsOverColumnLine(const X: Integer): Integer;
  94.     procedure SetAllCellPosition;
  95.     procedure SetGridLineColor(AValue: TColor);
  96.     procedure SetGridLineStyle(AValue: TPenStyle);
  97.     procedure SetGridLineWidth(AValue: Integer);
  98.     function TotalGridWidth: Integer;
  99.  
  100.     procedure MouseDownMyGrid(Sender: TObject; Button: TMouseButton;
  101.                               Shift: TShiftState; X, Y: Integer);
  102.     procedure MouseUpMyGrid(Sender: TObject; Button: TMouseButton;
  103.                           Shift: TShiftState; X, Y: Integer);
  104.     procedure MouseMoveMyGrid(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  105.  
  106.   protected
  107.     { Protected declarations }
  108.     procedure Paint; override;
  109.  
  110.   public
  111.     constructor Create(AOwner: TComponent); override;
  112.     destructor Destroy; override;
  113.  
  114.     property GridLineColor: TColor read FGridLineColor write SetGridLineColor default clSilver;
  115.     property GridLineStyle: TPenStyle read FGridLineStyle write SetGridLineStyle;
  116.     property GridLineWidth: Integer read FGridLineWidth write SetGridLineWidth default 1;
  117.   end;
  118.  
  119.   TMyGrid = class(TMyCustomGrid)
  120.   published
  121.   end;
  122.  
  123.  
  124. implementation
  125.  
  126. { TMyGridColumn }
  127.  
  128. procedure TMyGridColumn.SetWidth(AValue: Integer);
  129. begin
  130.   if FWidth=AValue then Exit;
  131.   FWidth:=AValue;
  132. end;
  133.  
  134. constructor TMyGridColumn.Create;
  135. begin
  136.  
  137. end;
  138.  
  139. destructor TMyGridColumn.Destroy;
  140. begin
  141.   inherited Destroy;
  142. end;
  143.  
  144. { TCustomMyCell }
  145.  
  146. procedure TCustomMyCell.SetFooter(AValue: string);
  147. begin
  148.   _lblFooter.Caption:= AValue;
  149. end;
  150.  
  151.  
  152. function TCustomMyCell.GetFooter: string;
  153. begin
  154.   Result:= _lblFooter.Caption;
  155. end;
  156.  
  157. function TCustomMyCell.GetHeader: string;
  158. begin
  159.   Result:= _lblHeader.Caption;
  160. end;
  161.  
  162. procedure TCustomMyCell.SetHeader(AValue: string);
  163. begin
  164.   _lblHeader.Caption:= AValue;
  165. end;
  166.  
  167. procedure TCustomMyCell.MouseDownCell(Sender: TObject;
  168.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  169. begin
  170.   TMyGrid(Self.Parent).OnMouseDown(Self, Button, Shift, X, Y);
  171. end;
  172.  
  173. procedure TCustomMyCell.MouseMoveCell(Sender: TObject;
  174.   Shift: TShiftState; X, Y: Integer);
  175. begin
  176.   TMyGrid(Self.Parent).OnMouseMove(Self, Shift, X, Y);
  177. end;
  178.  
  179. procedure TCustomMyCell.MouseUpCell(Sender: TObject;
  180.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  181. begin
  182.   TMyGrid(Self.Parent).OnMouseUp(Self, Button, Shift, X, Y);
  183. end;
  184.  
  185. constructor TCustomMyCell.Create(AOwner: TComponent);
  186. begin
  187.   inherited Create(AOwner);
  188.   // _lblFooter
  189.   _lblFooter:= TLabel.Create(Self);
  190.   _lblFooter.Align:= alBottom;
  191.   _lblFooter.AutoSize:= True;
  192.   _lblFooter.OnMouseDown:= @MouseDownCell;
  193.   _lblFooter.OnMouseMove:= @MouseMoveCell;
  194.   _lblFooter.OnMouseUp:= @MouseUpCell;
  195.   _lblFooter.Parent:= Self;
  196.   // _lblHeader
  197.   _lblHeader:= TLabel.Create(Self);
  198.   _lblHeader.Align:= alTop;
  199.   _lblHeader.AutoSize:= True;
  200.   _lblHeader.OnMouseDown:= @MouseDownCell;
  201.   _lblHeader.OnMouseMove:= @MouseMoveCell;
  202.   _lblHeader.OnMouseUp:= @MouseUpCell;
  203.   _lblHeader.Parent:= Self;
  204.   // _myviewer
  205.   _myviewer:= TPanel.Create(Self);
  206.   _myviewer.Align:= alClient;
  207.   _myviewer.AutoSize:= True;
  208.   _myviewer.OnMouseDown:= @MouseDownCell;
  209.   _myviewer.OnMouseMove:= @MouseMoveCell;
  210.   _myviewer.OnMouseUp:= @MouseUpCell;
  211.   _myviewer.Parent:= Self;
  212.  
  213.   OnMouseDown:= @MouseDownCell;
  214.   OnMouseMove:= @MouseMoveCell;
  215.   OnMouseUp:= @MouseUpCell;
  216. end;
  217.  
  218. destructor TCustomMyCell.Destroy;
  219. begin
  220.   inherited Destroy;
  221. end;
  222.  
  223. { TMyCustomGrid }
  224.  
  225. procedure TMyCustomGrid.CreateMyCells;
  226. var
  227.   i, j: Integer;
  228.   mycell: TMyCell;
  229. begin
  230.   for j:= 0 to RowCount - 1 do begin
  231.     for i:= 0 to ColCount - 1 do begin
  232.       mycell:= CreateMyCell(i, j);
  233.       _mycells.Add(mycell);
  234.     end;
  235.   end;
  236. end;
  237.  
  238. function TMyCustomGrid.IsOverColumnLine(const X: Integer): Integer;
  239. var
  240.   i, colidx, collineleft, margin: Integer;
  241. begin
  242.   colidx:= -1;
  243.   margin:= 2;
  244.   collineleft:= 0;
  245.   for i:= 0 to _columns.Count - 1 do begin
  246.     collineleft:= collineleft + GridLineWidth + _columns[i].Width;
  247.     if (X >= (collineleft - margin)) and (X <= (collineleft + margin)) then begin
  248.       colidx:= i;
  249.       Break;
  250.     end;
  251.   end;
  252.   Result:= colidx
  253. end;
  254.  
  255. procedure TMyCustomGrid.MouseDownMyGrid(Sender: TObject;
  256.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  257. var
  258.   cellIdx: Integer;
  259. begin
  260.   _resizingcolumnID:= IsOverColumnLine(X);
  261.   if _resizingcolumnID >= 0 then begin
  262.     Screen.Cursor:= crHSplit;
  263.     GetCursorPos(_oldCursorPos);
  264.   end;
  265. end;
  266.  
  267. procedure TMyCustomGrid.MouseUpMyGrid(Sender: TObject;
  268.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  269. begin
  270.   _resizingcolumnID:= -1;
  271. end;
  272.  
  273. procedure TMyCustomGrid.MouseMoveMyGrid(Sender: TObject;
  274.   Shift: TShiftState; X, Y: Integer);
  275. var
  276.   newWidth: Integer;
  277.   newPos: TPoint;
  278. begin
  279.   if IsOverColumnLine(X) >= 0 then
  280.     Screen.Cursor:= crHSplit
  281.   else
  282.     Screen.Cursor:= crDefault;
  283.   // resize column
  284.   if _resizingcolumnID >= 0 then
  285.   begin
  286.     GetCursorPos(newPos);
  287.     newWidth:= _columns[_resizingcolumnID].Width + newPos.x - _oldCursorPos.x;
  288.     _oldCursorPos:= newPos;
  289.     if newWidth > MIN_COL_WIDTH then begin
  290.       _columns[_resizingcolumnID].Width:= newWidth;
  291.       Invalidate;
  292.     end;
  293.   end;
  294. end;
  295.  
  296. procedure TMyCustomGrid.SetAllCellPosition;
  297. var
  298.   i, j: Integer;
  299.   mycell: TMyCell;
  300. begin
  301.   for j:= 0 to RowCount - 1 do begin
  302.     for i:= 0 to ColCount - 1 do begin
  303.       mycell:= _mycells[j * ColCount + i];
  304.       setcellposition(i, j, mycell);
  305.     end;
  306.   end;
  307. end;
  308.  
  309. procedure TMyCustomGrid.SetGridLineColor(AValue: TColor);
  310. begin
  311.   if FGridLineColor=AValue then Exit;
  312.   FGridLineColor:=AValue;
  313.   Invalidate;
  314. end;
  315.  
  316. procedure TMyCustomGrid.SetGridLineStyle(AValue: TPenStyle);
  317. begin
  318.   if FGridLineStyle=AValue then Exit;
  319.   FGridLineStyle:=AValue;
  320.   Invalidate;
  321. end;
  322.  
  323. procedure TMyCustomGrid.SetGridLineWidth(AValue: Integer);
  324. begin
  325.   if FGridLineWidth=AValue then Exit;
  326.   FGridLineWidth:=AValue;
  327.   Invalidate;
  328. end;
  329.  
  330. procedure TMyCustomGrid.setcellposition(const aCol, aVisibleRow: Integer;
  331.   mycell: TMyCell);
  332. var
  333.   aTop, aLeft, aHeight, aWidth: Integer;
  334. begin
  335.   getcellposition(aCol, aVisibleRow, aTop, aLeft, aHeight, aWidth);
  336.   with mycell do begin
  337.     Top:= aTop;
  338.     Left:= aLeft;
  339.     Height:= aHeight;
  340.     Width:= aWidth;
  341.   end;
  342. end;
  343.  
  344. procedure TMyCustomGrid.getcellpositionstd(const aCol,
  345.   aVisibleRow: Integer; out aTop, aLeft, aHeight, aWidth: Integer);
  346. var
  347.   i, cheight, leftOffset: Integer;
  348. begin
  349.   aWidth:= _columns[aCol].Width;
  350.   // calculates Left offset (due to horizontal scrollbar position)
  351.   leftOffset:= 0;
  352.   // calculates left
  353.   aLeft:= GridLineWidth;
  354.   for i:= 0 to aCol - 1 do
  355.     aLeft:= aLeft + _columns[i].Width + GridLineWidth;
  356.   aLeft:= aLeft - leftOffset;
  357.   // calculates cell height
  358.   cheight:= getgridclientheight;
  359.   aHeight:= cheight div RowCount;
  360.   // calculates Top
  361.   aTop:= aVisibleRow * aHeight + ((aVisibleRow + 1) * GridLineWidth);
  362. end;
  363.  
  364.  
  365. procedure TMyCustomGrid.getcellposition(const aCol, aVisibleRow: Integer; out
  366.   aTop, aLeft, aHeight, aWidth: Integer);
  367. begin
  368.   getcellpositionstd(aCol, aVisibleRow, aTop, aLeft, aHeight, aWidth);
  369. end;
  370.  
  371. function TMyCustomGrid.getgridclientwidth: Integer;
  372. var
  373.   cwidth: Integer;
  374. begin
  375.   cwidth:= Self.ClientWidth;
  376.   // subtract grid lines width
  377.   Result:= cwidth - (ColCount + 1) * GridLineWidth;
  378. end;
  379.  
  380. function TMyCustomGrid.getgridclientheight: Integer;
  381. var
  382.   cheight: Integer;
  383. begin
  384.   cheight:= ClientHeight;
  385.   // subtract grid lines width
  386.   Result:= cheight - (RowCount + 1) * GridLineWidth;
  387. end;
  388.  
  389. procedure TMyCustomGrid.updatecolumns(const newlength: Integer);
  390. var
  391.   newcol: TMyGridColumn;
  392.   i, prevcolcount: Integer;
  393. begin
  394.   prevcolcount:= _columns.Count;
  395.   if newlength > prevcolcount then begin
  396.     for i:= prevcolcount + 1 to newlength do begin
  397.       newcol:= TMyGridColumn.Create;
  398.       newcol.Width:= DEFAULT_COLUMN_SIZE;
  399.       _columns.Add(newcol);
  400.     end;
  401.   end;
  402.   if newlength < prevcolcount then begin
  403.     for i:= prevcolcount - 1 downto newlength do
  404.       _columns.Delete(i);
  405.   end;
  406. end;
  407.  
  408. function TMyCustomGrid.CreateMyCell(aCol, aRow: Integer
  409.   ): TMyCell;
  410. var
  411.   mycell: TMyCell;
  412. begin
  413.   mycell:= TMyCell.Create(Self);
  414.   mycell.Name:= format('%s%d', [MYCELLNAME, _mycells.Count + 1]);
  415.   mycell.Parent:= Self;
  416.   Result:= mycell;
  417. end;
  418.  
  419. procedure TMyCustomGrid.DrawAllRows;
  420. var
  421.   i: Integer;
  422. begin
  423.   for i:= 0 to RowCount - 1 do begin
  424.     DrawRow(i);
  425.   end;
  426. end;
  427.  
  428. procedure TMyCustomGrid.DrawMyCellGrid(aCol, aRow: Integer);
  429. var
  430.   aRect: TRect;
  431.   aWidth, aTop, aLeft, aHeight, correction: Integer;
  432. begin
  433.   with Canvas do begin
  434.     if fGridLineWidth > 0 then begin
  435.       getcellposition(aCol, aRow, aTop, aLeft, aHeight, aWidth);
  436.       Pen.EndCap:= pecSquare;
  437.       Pen.Style := fGridLineStyle;
  438.       Pen.Color := FGridLineColor;
  439.       Pen.Width := fGridLineWidth;
  440.       correction:= 0;
  441.       correction:= FGridLineWidth div 2;
  442.       if (FGridLineWidth mod 2) <> 0 then
  443.         correction:= correction + 1;
  444.       aRect.Top:= aTop - correction;
  445.       aRect.Bottom:= aRect.Top + aHeight + (correction);
  446.       aRect.Left:= aLeft - correction;
  447.       aRect.Right:= aRect.Left + aWidth + (correction);
  448.       correction:= 0;
  449.       if FGridLineWidth > 1 then
  450.         correction:= Max(1, (FGridLineWidth div 2));
  451.       // draw bottom-aligned line
  452.       MoveTo(aRect.Left, aRect.Bottom + correction);
  453.       LineTo(aRect.Right + correction, aRect.Bottom + correction);
  454.       // draw right-aligned line
  455.       MoveTo(aRect.Right + correction, aRect.Top);
  456.       LineTo(aRect.Right + correction, aRect.Bottom + correction);
  457.       // if is the first visible row draw also the top-aligned line
  458.       if (aRow = 0) then begin
  459.         MoveTo(aRect.Left, aRect.Top);
  460.         LineTo(aRect.Right, aRect.Top);
  461.       end;
  462.       // if aCol = 0 draw also the left-aligned line
  463.       if (aCol = 0) then begin
  464.         MoveTo(aRect.Left, aRect.Top);
  465.         LineTo(aRect.Left, aRect.Bottom);
  466.       end;
  467.     end;
  468.   end;
  469. end;
  470.  
  471. procedure TMyCustomGrid.DrawRow(aRow: Integer);
  472. var
  473.   i: Integer;
  474. begin
  475.   for i:= 0 to ColCount - 1 do begin
  476.     DrawMyCellGrid(i, aRow);
  477.   end;
  478. end;
  479.  
  480. procedure TMyCustomGrid.DestroyMyCells;
  481. begin
  482.   _mycells.Clear;
  483. end;
  484.  
  485.  
  486. function TMyCustomGrid.TotalGridWidth: Integer;
  487. var
  488.   i, gwidth: Integer;
  489. begin
  490.   gwidth:= GridLineWidth;
  491.   for i:= 0 to _columns.Count - 1 do begin
  492.     gwidth:= gwidth + _columns[i].Width + GridLineWidth;
  493.   end;
  494.   Result:= gwidth;
  495. end;
  496.  
  497. procedure TMyCustomGrid.Paint;
  498. begin
  499.   if _mycells.Count = (RowCount * ColCount) then begin
  500.     SetAllCellPosition;
  501.     DrawAllRows;
  502.   end;
  503.   inherited Paint;
  504. end;
  505.  
  506.  
  507. constructor TMyCustomGrid.Create(AOwner: TComponent);
  508. begin
  509.   inherited Create(AOwner);
  510.   ControlStyle:= ControlStyle - [csNoFocus];
  511.   Color:= clWhite;
  512.   BorderStyle:= bsSingle;
  513.   OnMouseMove:= @MouseMoveMyGrid;
  514.   OnMouseDown:= @MouseDownMyGrid;
  515.   OnMouseUp:= @MouseUpMyGrid;
  516.  
  517.   FGridLineColor:=clSilver;
  518.   FGridLineStyle:=psSolid;
  519.   FGridLineWidth := 1;
  520.  
  521.   _resizingcolumnID:= -1;
  522.   _columns:= TMyGridColumns.Create;
  523.   updatecolumns(ColCount);
  524.   _mycells:= TMyCellList.Create(True);
  525.   CreateMyCells;
  526.   SetInitialBounds(0, 0, 200, 150);
  527. end;
  528.  
  529. destructor TMyCustomGrid.Destroy;
  530. begin
  531.   if Assigned(_columns) then
  532.     _columns.Free;
  533.   if Assigned(_mycells) then
  534.     _mycells.Free;
  535.   inherited Destroy;
  536. end;
  537.  
  538. end.
  539.  

What am I doing wrong? What can I do to improve column resizing performance?
« Last Edit: March 21, 2018, 03:09:39 pm by apeoperaio »

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: column resize in grid-like custom component
« Reply #1 on: March 19, 2018, 01:50:25 pm »
I don't think its column resizing problem. The problem is how you create grid, every cell is object. 20cols x 100rows will give 2000 objects for compute sizes etc.
Orginal grids based on OnDraw method for painting only visible grid and TFPList for data.
Maybe better you should modify grids.pas and adapt to your needs ?

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: column resize in grid-like custom component
« Reply #2 on: March 19, 2018, 01:56:10 pm »
In your case it is not drawing what causes slowness. It is resizing.
Your component consists or 42 cells and each cell contains two TLabels and one TPanel. Together it is 169 components. Each resizing recursively calls resizing of all components and it all is in the end slow.

When I commented the code in TCustomMyCell.Create that creates those three components (components is reduced to 43) it become fast.

I recommend you: do not use labels. Use DrawText; instead. Consider if it is really necessary to have every Cell TCustomControl. I don't know what is purpose of this component. Anyway, current design has very big overhead.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: column resize in grid-like custom component
« Reply #3 on: March 19, 2018, 02:19:50 pm »
In your case it is not drawing what causes slowness. It is resizing.
Your component consists or 42 cells and each cell contains two TLabels and one TPanel. Together it is 169 components. Each resizing recursively calls resizing of all components and it all is in the end slow.

When I commented the code in TCustomMyCell.Create that creates those three components (components is reduced to 43) it become fast.

I recommend you: do not use labels. Use DrawText; instead. Consider if it is really necessary to have every Cell TCustomControl. I don't know what is purpose of this component. Anyway, current design has very big overhead.

Ok, thanks for the explanation. You reccomend to draw directly on my grid canvas instead of creating many components. If I need to write a text should I use DrawText or TextOut?
I will try to modify my class accordingly.

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: column resize in grid-like custom component
« Reply #4 on: March 19, 2018, 02:42:44 pm »
There's Canvas.TextOut for common purposes. You can also use unit Themes and ThemeServices.DrawText where you have more possibilities like disabled text.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: column resize in grid-like custom component
« Reply #5 on: March 21, 2018, 03:09:09 pm »
I modified my component directly drawing on its canvas and now it works very smoothly!
Thanks for all the suggestion.

 

TinyPortal © 2005-2018