2

我有一个TScrollBox垂直滚动,水平滚动条被禁用。在这个滚动框内,有一个与顶部对齐的大面板,其高度是根据其内容动态计算的。它的内容是两个面板,一个向左对齐,另一个对齐客户端,中间有一个拆分器。在这两个面板中的每一个内部,都有一系列与顶部对齐的用户选择的面板,它们也可以动态调整大小,从而扩展/减少滚动框中主面板的高度。

procedure TfrmDashboard.ResizePanels;
var
  X: Integer;
  H1, H2: Integer;
  H: Integer;
begin
  H1:= 0;
  H2:= 0;
  //Calculate height of left panel
  for X := 0 to p1.ControlCount-1 do
    H1:= H1 + p1.Controls[X].Height;
  //Calculate height of right panel
  for X := 0 to p2.ControlCount-1 do
    H2:= H2 + p2.Controls[X].Height;
  //Check which panel is larger
  H:= H1;
  if H2 > H then
    H:= H2;
  //Adjust scrolling height
  pMain.Height:= H + 10;
  SB.VertScrollBar.Range:= pMain.Height;
  SB.VertScrollBar.Size:= pMain.Height;
end;

同时,这些较小的内容子面板中的大多数还具有接收焦点的控件,并且需要允许获得焦点。目前滚动一切正常。

当用户单击滚动框中的此类可聚焦控件之一时,就会出现问题。如果该控件碰巧被部分隐藏(控件的顶部延伸到滚动位置的顶部上方),则整个滚动框会向上跳转以将该控件定位在滚动框的顶部。

这似乎是一个“功能”,但我想禁用一个功能。在这种情况下很烦人。当其中一个孩子获得焦点时,如何防止滚动框跳跃位置?

4

1 回答 1

4

这是 TScrollBox 的默认行为,没有属性可以关闭此功能。
但是您可以通过子类化 TScrollBox 来更改此行为,并改用这个新类:

TModifiedScrollBox=class(TScrollBox)
protected
    procedure AutoScrollInView(AControl:TControl); override;
end;

procedure TModifiedScrollBox.AutoScrollInView(AControl:TControl);
begin
  // empty body
end;

此代码的缺点是如果您在自己的代码中使用 AutoScrollInView 将停止工作。但是如果你仍然需要这个方法,你可以创建额外的方法来“保存”它:

TModifiedScrollBox=class(TScrollBox)
protected
    procedure AutoScrollInView(AControl:TControl); override;
    procedure AutoScrollInViewSave(AControl:TControl);
end;

procedure TModifiedScrollBox.AutoScrollInViewSave(AControl:TControl);
begin
  // forward to base implementation
  inherited AutoScrollInView(AControl);
end;

然后在您的代码中,您应该为这个新类替换所有对 AutoScrollInViewSave 的 AutoScrollInView 调用。

PS 在幕后,每次新控件获得焦点时,TCustomForm 都会为所有焦点控件的父控件调用 AutoScrollInView。

于 2015-11-25T04:57:56.007 回答