It's a Windows limitation: the size of a Windowed control cannot exceed 65,535 pixels.
See the documentation on the WM_SIZE message wherein width and height are passed together in a single 32 bit parameter:
lParam
The low-order word of lParam specifies the new width of the client area.
The high-order word of lParam specifies the new height of the client area.
So width and height values are limited to 16 bits. That is: when SetWindowPos
or alike is involved, which is called by SetBounds
, which is called by setting Top
.
Subsequently, the Top
value of a control, which can be negative, is limited to 15 bits and 1 sign bit, thus +-32,767. To be specific: that is where Control.ClientOrigin.X/Y
is bound by. E.g. thus resolving in a maximum Top
value of 32,167 for a control placed in the middle of a 1920x1200 pixel screen.
So this is why the last panels appear on the same spot within your scroll box.
Note that this limitation does not apply to VCL controls without Windows handle.
How to solve?
The Top
property of a child control within a scroll box is relative to the box's visible clientrect; scrolling the scroll bar resets the Top
properties of all children.
So (just) before reaching the magic limit, fool Windows by scrolling the scroll box:
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
J: Integer;
P: TPanel;
begin
ScrollBox1.DisableAlign;
try
ScrollBox1.VertScrollBar.Range := 400 * 202; // 80,800 ! ;-)
for I := 0 to 3 do
begin
ScrollBox1.VertScrollBar.Position := I * 100 * 202;
for J := 0 to 99 do
begin
P := TPanel.Create(Self);
P.SetBounds(0, J * 202, 100, 200);
P.Align := alCustom;
P.Caption := IntToStr(I * 100 + J);
P.ParentBackground := False;
P.Color := Random(clWhite);
P.Parent := ScrollBox1;
end;
end;
finally
ScrollBox1.VertScrollBar.Position := 0;
ScrollBox1.EnableAlign;
end;
end;
How to solve it better?
Instead of TPanel
(a TWinControl
), use TControl
derivatives to bypass API calls to SetWindowPos
.
How to solve it best?
Use a virtual approach, like TDBControlGrid
does, showing only a few panels while giving the impression of having a lot.