Recent

Author Topic: [SOLVED] Custom control, dynamic resizing and problems with anchors  (Read 495 times)

furious programming

  • Hero Member
  • *****
  • Posts: 853
I'm trying to write a test component, based on TCustomControl, a simple grid. Its size should adjust automatically after adding or removing items. The sizing update is intended to apply only to the height of the component.

The problem I have is that I don't know how to force the size of the component in the method that adds a new item. For now, I override the ChangeBounds method — in it I calculate the new height and pass it to inherited ChangeBounds. After adding a new item, I force the component's size to be recalculated by calling ChangeBounds(Left, Top, Width, Height), i.e. giving the current size of the control, because there are height calculations in the overwritten ChangeBounds.

It works, the component correctly recalculates the height and updates it. The problem however is that if I anchor the component to the right side of the window so that it changes width as the window is resized, the width doesn't change at all. I don't know why.



Can someone tell me how to properly program the component so that it adjusts its height to its own calculations and reacts correctly to anchors? Which methods to use and in which one to implement my own calculation of the height of the control?

Let's assume that there is a FItemsCount field in the component, the item cell size is 32x64 pixels, and the calculation of the new height looks like this:

Code: Pascal  [Select][+][-]
  1. ItemCols := Self.Width div 32; // divide by the cell width
  2. ItemRows := FItemsCount div ItemCols + Ord(FItemsCount mod ItemCols > 0);

Now the ItemRows contains the number of rows, so multiply it by the item cell height (which is 64 pixels) and this is the new control height. Where these calculations should be and how to properly force the control to update its size?
« Last Edit: June 01, 2023, 07:20:04 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Custom control, dynamic resizing and problems with anchors
« Reply #1 on: June 01, 2023, 06:23:59 pm »
Most likely not relevant but, the cords for the Width are actually the right and bottom of the control.

Maybe you need to add the LEFT to the WIDTH to get the correct right side value.

 Also, the anchors do take control of this, you could test the anchor fields for the and shift the LEFT side over.
The only true wisdom is knowing you know nothing

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Custom control, dynamic resizing and problems with anchors
« Reply #2 on: June 01, 2023, 06:26:56 pm »
Note that I'm only interested in modifying the height of the component — its width and position should be controlled by LCL.
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Custom control, dynamic resizing and problems with anchors
« Reply #3 on: June 01, 2023, 06:41:06 pm »
Ok, then the bounds value for that would be the TOP+NewHeight.

You need to offset the height with the TOP.

I know if you look at the DOC's it gets confusing when they refer to the last two parameters as the width and height.

It should be the right and bottom location.

 You can test this simply by displaying the value of the form's BoundsRect.Right as you move it around, it will represent the location not the actual width.

 But, you can get the size of the control using these values of course.

 If the Top or bottom isn't anchored then it should work.

Why not simply use the Height property ?
The only true wisdom is knowing you know nothing

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Custom control, dynamic resizing and problems with anchors
« Reply #4 on: June 01, 2023, 06:50:52 pm »
You are writing off topic. I wrote that the only thing I'm interested in is adjusting the height of the component in relation to my own calculations — the rest, i.e. the width and position of the component, should not be modified, because they must be managed by LCL (so that the width adjusts automatically, according to the set anchors).

Well, I'm changing the height, the component actually has the height according to the calculations, but in runtime the width of the component does not change at all, despite the fact that the component is anchored to the right edge of the window (when stretching the window, the component maintains a fixed width). In design time it resizes automatically, in runtime it doesn't. No matter if I overwrite ChangeBounds or in the Resize method I calculate a new height and assign it to the component's Height property, the height is always as calculated, but the width is not automatically set by LCL (anchors are ignored).

Anyone know why this is happening and how to force the component to respect these anchors? See attachments:

1.png — design time, standard size
2.png — design time, after stretching window (the component respects anchors)
3.png — runtime, standard size
4.png — runtime, after stretching window (the component maintain its width, it ignores anchors).

My test component is nested in the ScrollBox and is anchored to the left and right of it. ScrollBox is anchored to the left and right of the window. If I change the width of the window, the ScrollBox adjusts its size (respects anchors), but my test component does not adjust the width to the ScrollBox. This problem exists only in runtime. Now it should be clear what is going on.
« Last Edit: June 01, 2023, 06:59:22 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Custom control, dynamic resizing and problems with anchors
« Reply #5 on: June 01, 2023, 07:18:48 pm »
Ok, I know where the problem was. Jesus Christ...

I forget to add Anchors property in the published section of my component, so setting anchors in the Anchor Editor actually does not store them in the test project files. So, when I close the form editor and open again, the right anchor was not set (which is the default behavior) and because anchors are not stored, at runtime they were default (top and left only). That is why the component ”ignores” them.

So everything is fine, it was my fault — stupid mistake. Problem solved.



If somebody would like to know how to do it, just override the Resize method and in it, calculate new height of the control and finally assign it to the Height property. To force the control to adjust its size, just call Resize(). This solution works but I don't know it is universal and works with all possible anchors and align settings. For simple things it is enough.

The current code of my test component looks like this:

Code: Pascal  [Select][+][-]
  1. procedure TCustomTestGrid.Resize();
  2. begin
  3.   inherited Resize();
  4.  
  5.   if FItems.Count > 0 then
  6.   begin
  7.     FItemCols := Width div FItemWidth;
  8.     FItemRows := FItems.Count div FItemCols + Ord(FItems.Count mod FItemCols > 0);
  9.  
  10.     Self.Height := FItemRows * FItemHeight; // adjust the control height to the number of items
  11.   end
  12.   else
  13.     if not (csDesigning in ComponentState) then
  14.       Self.Height := 0; // at runtime, when no items, component should have 0-height
  15. end;

Works perfectly.
« Last Edit: June 01, 2023, 07:34:37 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

 

TinyPortal © 2005-2018