Delphi - TScrollBox问题后X个组件 [英] Delphi - TScrollBox issue after X number of components
问题描述
所以我创建了一个新项目来尝试识别和解决问题,并且显示了一个额外的细节问题。当我回家的时候,我可以提供一个例子和一个视频,但现在我将会描述。用TScrollBox做一个spinedit的表单来指定一个按钮在一个循环中创建面板的按钮,以及一个按钮来释放面板并清空数组以进行另一次尝试。我将标题设置为循环中的号码进行识别。
我已经尝试了两种堆叠方式,以查看位是否重要。一个是设置位置I倍高度,所以如果height是200,那么我* 202给它一个2px的空间。我尝试的新方法是使用对齐顶部。它可能有一个微小的差异,但一般的问题仍然是一样的。
新的问题是滚动范围。循环完成后,滚动框可以滚动到最后编号面板的底部。但它的位置可能是199在169它的200面板。然后滚动条调整范围,让我到达底部才能看到最后面板198的下一个。我相信这是使用对齐顶部方法,因为它从未在我的应用程序中发生。我会进一步测试。
底部面板不放在一边我认为该问题的解决方案是手动计算和设置范围。
在设置位置而不是使用对齐顶部时,在我的应用程序中发生的主要问题是,在一定数量的面板之后,它们都位于同一位置。在一定数量之前,罚款是50或100,但经过这么多事情发生。我知道200次200是一个很小的整数,但也许有一个地址限制?
我将继续测试,我仍然需要检查是否增加面板高度。但是想到这是一个已知的问题。
这是Windows限制:Windowed控件的大小不能超过65,535像素。 >
请参阅 WM_SIZE消息,其中宽度和高度以单个32位参数传递在一起:
lParam
lParam的低位词指定客户区域的新宽度。
lParam的高位词指定客户区域的新高度。
因此,width和height值限制为16位。也就是说:当 SetWindowPos
或相似的方式,由 SetBounds
调用,通过设置顶部
。
随后,控件的 Top
值可以为负,限制在15位和1位符号位,因此+ -32,767。具体说来:那就是 Control.ClientOrigin.X / Y
的绑定。例如。因此,对于放置在1920x1200像素屏幕中间的控件,解析最大顶部
值为32,167。
所以这就是为什么最后一个面板出现在滚动条中的同一个位置。
请注意,此限制不适用于没有Windows句柄的VCL控件。
如何解决?
/ code>滚动框内的子控件的属性是相对于框的可见客户端;滚动滚动条将重置所有孩子的
顶部
属性。
所以(只是)达到魔法极限之前,愚弄Windows滚动滚动框:
procedure TForm1.Button1Click(Sender:TObject);
var
I:整数;
J:整数;
P:TPanel;
begin
ScrollBox1.DisableAlign;
try
ScrollBox1.VertScrollBar.Range:= 400 * 202; // 80,800! ; -)
为I:= 0到3 do
begin
ScrollBox1.VertScrollBar.Position:= I * 100 * 202;
为J:= 0到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:=随机(clWhite);
P.Parent:= ScrollBox1;
结束
结束
finally
ScrollBox1.VertScrollBar.Position:= 0;
ScrollBox1.EnableAlign;
结束
结束
如何更好地解决?
而不是 TPanel
(a TWinControl
),使用 TControl
衍生物绕过API调用 SetWindowPos
。
如何最好地解决?
使用虚拟方法,如 TDBControlGrid
只显示几张面板,同时给人印象很深。
I noticed in one of my test applications after I have added so many TPanels to a TScrollBox I run into a problem with the ones drawn past that certain amount. I disable the scroll box prior to drawing and it is always cleared before drawing so there are no relative position problems. Initially I thought maybe I had run into some sort of maximum height to paint. So you know the arrangement is width occupying panels stacked vertically.
So I created a new project to try and identify and tackle the problem and it has revealed an additional detail to the problem. When I'm home I can provide the example and a video but I will describe for now. Made a form with a TScrollBox a spinedit to specify how many panels a button to create the panels in a loop and a button to free the panels and empty the array for another try. I set the caption to the number in the loop for identification.
I have tried 2 ways of stacking to see if bit mattered. One is to set the position I times height so if height is 200 then i * 202 giving it a space of 2px. The new way I tried was using align top instead. It might have a slight difference in effect but the problem in general is still the same.
The new problem is with the scroll range. After the loop is done and the scroll box is enabled scrolling down to the bottom stops at the last numbered panel. But its out of place maybe 199 right below 169 its 200 panels. Then the scroll bar adjusts range letting me reach the bottom only to see the next to last panel 198. I believe this occurs using the align top method as it never occurred in my app. I will test further.
Bottom panel not placing aside I think the solution to that problem is to manually calculate and set the range.
The main problem which occurs in my app when setting the position instead of using align top is that after a certain number of panels they all position at the end in the same spot. Before a certain amount its fine say 50 or 100 but after so many it happens. I know 200 times 200 is a pretty small integer but maybe there is a address limit?
I will continue to test I still need to check if panel height adds into it. But figured this has to be a known issue. Delphi 2009 by the way.
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.
这篇关于Delphi - TScrollBox问题后X个组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!