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

时间:2011-08-19 07:18:28

标签: delphi scroll

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

当我向下滚动到我想要查看部分文本控件的位置,然后调用DoTask时,ScrollBox将自动滚动到RichEdit的顶部。我怎么能避免这种情况?

3 个答案:

答案 0 :(得分:7)

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

  • 在表单中覆盖SetFocusedControl

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

    或者:

    type
      TCustomMemoAccess = class(TCustomMemo);
    
    function TForm1.SetFocusedControl(Control: TWinControl): Boolean;
    var
      Memo: TCustomMemoAccess;
      Scroller: TScrollingWinControl;
      Pt: TPoint;
    begin
      Result := inherited SetFocusedControl(Control);
      if (Control is TCustomMemo) and (Control.Parent <> nil) and
        (Control.Parent is TScrollingWinControl) then
      begin
        Memo := TCustomMemoAccess(Control);
        Scroller := TScrollingWinControl(Memo.Parent);
        SendMessage(Memo.Handle, EM_POSFROMCHAR, Integer(@Pt), Memo.SelStart);
        Scroller.VertScrollBar.Position := Scroller.VertScrollBar.Position +
          Memo.Top + Pt.Y;
      end;
    end;
    
  • 介入TScrollBox

    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;
    

或使用上述所有创意组合。你喜欢滚动的方式和时间只有你知道。

答案 1 :(得分:2)

最简单的解决方案是

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

答案 2 :(得分:1)

如果没有攻击VCL /派生自定义组件,那么只有一个解决方案--TForm.SetFocusedControl覆盖+重新设置滚动条的位置,如上所述。我添加的一件事是禁用/启用窗口重绘以避免丑陋的跳跃。 这是我最后的片段:

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;