Delphi 如何禁用TScrollBox的滚动查看行为?

Delphi 如何禁用TScrollBox的滚动查看行为?,delphi,scroll,Delphi,Scroll,我有一个TScrollBox,它的RichEdit比scrollbox大,因此两侧的滚动条都出现在滚动框中。然后我有一个函数DoTask,它调用RichEdit.SetFocus 当我向下滚动到希望看到部分文本控件的位置,然后调用DoTask,滚动框将自动滚动到RichEdit的顶部。如何避免这种情况?最简单的解决方案是 var a, b : Integer; begin a := ScrollBox1.VertScrollBar.Position; b := ScrollBox1.Ho

我有一个
TScrollBox
,它的RichEdit比scrollbox大,因此两侧的滚动条都出现在滚动框中。然后我有一个函数
DoTask
,它调用
RichEdit.SetFocus


当我向下滚动到希望看到部分文本控件的位置,然后调用
DoTask
,滚动框将自动滚动到RichEdit的顶部。如何避免这种情况?

最简单的解决方案是

var a, b : Integer;
begin
  a := ScrollBox1.VertScrollBar.Position;
  b := ScrollBox1.HorzScrollBar.Position;
  richEdit1.SetFocus;
  ScrollBox1.VertScrollBar.Position:=a ;
  ScrollBox1.HorzScrollBar.Position:=b ;
end;

如您所愿,以下是一些建议:

  • 重写
    SetFocusedControl
    ,格式如下:

    function TForm1.SetFocusedControl(Control: TWinControl): Boolean;
    begin
      if Control = RichEdit then
        Result := True
      else
        Result := inherited SetFocusedControl(Control);
    end;
    
    或:

    或:

    过程TScrollBox.autoScrollView(AControl:TControl);
    开始
    if(AControl.Top>VertScrollBar.Position+ClientHeight)异或
    (A控制顶部+A控制高度<垂直滚动条位置)然后
    继承的自动克隆视图(AControl);
    结束;
    

或者使用上述所有内容的任何创造性组合。只有你自己知道你喜欢滚动的方式和时间。

在不侵入VCL/派生自定义组件的情况下,只有一种解决方案-TForm.SetFocusedControl override+如上所述重新设置滚动条的位置。我添加的一件事是禁用/启用窗口重画以避免丑陋的跳转。 以下是我的最后一个片段:

sbContainer是TScrollBox,NoScrCtrl是一个放置在其中的控件,它可以获得焦点,但我们不希望它在视图中滚动

function TForm1.SetFocusedControl(Control: TWinControl): Boolean;
var hpos, vpos: integer;
begin
  if Control = NoScrCtrl then
  begin
    sbContainer.Perform(WM_SETREDRAW, WPARAM(False), 0);
    hpos := sbContainer.HorzScrollBar.Position;
    vpos := sbContainer.VertScrollBar.Position;
    Result := inherited SetFocusedControl(Control);
    sbContainer.HorzScrollBar.Position := hpos;
    sbContainer.VertScrollBar.Position := vpos;
    sbContainer.Perform(WM_SETREDRAW, WPARAM(True), 0);
    sbContainer.Refresh;
  end
  else
    Result := inherited SetFocusedControl(Control);
end;

不要使用滚动框似乎是一个显而易见的解决方案,因为你的滚动条比你的多needed@David:如果RichEdit是滚动框上的唯一组件,我同意。当然,我们不知道它是否是。将一个具有自己滚动条的组件放在滚动框上会有点。。。的确很奇怪。是的,除了richedit之外还有很多控件。我想TScrollBox的类助手,而不是插入器,也会起作用。“不过,我不能检查。我认为那不管用,”鲁迪说。不能使用类帮助器重写虚拟方法。该方法的原始调用站点不知道类帮助器存在,因此它将继续调用原始方法。@Rob:你说得对。原始调用站点将不使用helper方法。
type
  TScrollBox = class(Forms.TScrollBox)
  protected
    procedure AutoScrollInView(AControl: TControl); override;
  end;

procedure TScrollBox.AutoScrollInView(AControl: TControl);
begin
  if not (AControl is TCustomMemo) then
    inherited AutoScrollInView(AControl);
end;
procedure TScrollBox.AutoScrollInView(AControl: TControl);
begin
  if (AControl.Top > VertScrollBar.Position + ClientHeight) xor
      (AControl.Top + AControl.Height < VertScrollBar.Position) then
    inherited AutoScrollInView(AControl);
end;
function TForm1.SetFocusedControl(Control: TWinControl): Boolean;
var hpos, vpos: integer;
begin
  if Control = NoScrCtrl then
  begin
    sbContainer.Perform(WM_SETREDRAW, WPARAM(False), 0);
    hpos := sbContainer.HorzScrollBar.Position;
    vpos := sbContainer.VertScrollBar.Position;
    Result := inherited SetFocusedControl(Control);
    sbContainer.HorzScrollBar.Position := hpos;
    sbContainer.VertScrollBar.Position := vpos;
    sbContainer.Perform(WM_SETREDRAW, WPARAM(True), 0);
    sbContainer.Refresh;
  end
  else
    Result := inherited SetFocusedControl(Control);
end;