Delphi 如何防止滚动框中的控件跳转到焦点?

Delphi 如何防止滚动框中的控件跳转到焦点?,delphi,focus,delphi-xe7,tscrollbox,Delphi,Focus,Delphi Xe7,Tscrollbox,我有一个垂直滚动的TScrollBox,水平滚动条被禁用。在这个滚动框中,有一个与顶部对齐的大面板,其高度根据其内容动态计算。它的内容是两个面板,一个与左侧对齐,另一个与客户端对齐,中间有一个拆分器。在这两个面板中的每个面板内,都有一系列与顶部对齐的用户选择面板,这些面板也可以动态调整大小,从而扩展/减小滚动框内主面板的高度 procedure TfrmDashboard.ResizePanels; var X: Integer; H1, H2: Integer; H: Intege

我有一个垂直滚动的
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;
同时,这些较小的内容子面板中的大多数还具有接收焦点的控件,并且需要允许获得焦点。目前,滚动一切正常

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

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;

这似乎是一个“功能”,但我想禁用它。在这种情况下很烦人。当滚动框的一个子项接收到焦点时,如何防止滚动框跳转位置?

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

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

procedure TModifiedScrollBox.AutoScrollInView(AControl:TControl);
begin
  // empty body
end;
此代码的缺点是,如果在自己的代码中使用AutoScrolinView,它将停止工作。但如果您仍然需要此方法,您可以创建其他方法来“保存”它:

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


PS在引擎盖下,每次新控件被聚焦时,TCustomForm都会为所有聚焦控件的父控件调用AutoScrolnView。

老实说,我的解释的前半部分与问题无关,只是设置了示例的基础。