如何禁用 TScrollBox 的滚动到视图行为?

发布于 2024-11-30 12:19:15 字数 209 浏览 0 评论 0原文

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

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

I have a TScrollBox that has a RichEdit that is bigger than the scrollbox, so both side scrollbars appear in the scrollbox. Then I have a function DoTask that calls RichEdit.SetFocus.

When I scroll down to where I want to see part of the text control, and then call DoTask, the ScrollBox will automatically scroll to the top of the RichEdit. How can I avoid that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

凶凌 2024-12-07 12:19:15

如您所愿,这里有一些建议:

  • 以以下形式覆盖SetFocusedControl

    函数 TForm1.SetFocusedControl(Control: TWinControl): Boolean;
    开始
      如果 Control = RichEdit 那么
        结果:=真
      别的
        结果 := 继承 SetFocusedControl(Control);
    结尾;
    

    或者:

    <前><代码>类型
    TCustomMemoAccess = 类(TCustomMemo);

    函数 TForm1.SetFocusedControl(Control: TWinControl): Boolean;
    变量
    备忘录:TCustomMemoAccess;
    滚动条:TScrollingWinControl;
    Pt:T点;
    开始
    结果 := 继承 SetFocusedControl(Control);
    if (Control 是 TCustomMemo) and (Control.Parent <> nil) and
    (Control.Parent是TScrollingWinControl)然后
    开始
    备忘录 := TCustomMemoAccess(Control);
    滚动器 := TScrollingWinControl(Memo.Parent);
    SendMessage(Memo.Handle, EM_POSFROMCHAR, Integer(@Pt), Memo.SelStart);
    Scroller.VertScrollBar.Position := Scroller.VertScrollBar.Position +
    Memo.Top + Pt.Y;
    结尾;
    结尾;

  • Interpose TScrollBox

    <前><代码>类型
    TScrollBox = 类(Forms.TScrollBox)
    受保护的
    过程 AutoScrollInView(AControl: TControl);覆盖;
    结尾;

    过程 TScrollBox.AutoScrollInView(AControl: TControl);
    开始
    如果不是(AControl 是 TCustomMemo)那么
    继承 AutoScrollInView(AControl);
    结尾;

    或者:

    过程 TScrollBox.AutoScrollInView(AControl: TControl);
    开始
      if (AControl.Top > VertScrollBar.Position + ClientHeight) xor
          (AControl.Top + AControl.Height < VertScrollBar.Position) 然后
        继承 AutoScrollInView(AControl);
    结尾;
    

或者使用上述所有内容的任意创意组合。只有您知道如何以及何时滚动它。

As you wish, here are some suggestions:

  • Override SetFocusedControl in the form:

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

    Or:

    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;
    
  • Interpose 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;
    

    Or:

    procedure TScrollBox.AutoScrollInView(AControl: TControl);
    begin
      if (AControl.Top > VertScrollBar.Position + ClientHeight) xor
          (AControl.Top + AControl.Height < VertScrollBar.Position) then
        inherited AutoScrollInView(AControl);
    end;
    

Or use any creative combination of all of the above. How and when you like it to be scrolled only you know.

如梦亦如幻 2024-12-07 12:19:15

最简单的解决方案是

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

the simpliest solution would be

var a, b : Integer;
begin
  a := ScrollBox1.VertScrollBar.Position;
  b := ScrollBox1.HorzScrollBar.Position;
  richEdit1.SetFocus;
  ScrollBox1.VertScrollBar.Position:=a ;
  ScrollBox1.HorzScrollBar.Position:=b ;
end;
最终幸福 2024-12-07 12:19:15

在不侵入 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;

Without hacking into VCL/deriving custom components there's only one solution - TForm.SetFocusedControl override + re-setting the positions of scrollbars as said above. One thing I added is disabling/enabling window redraw to avoid ugly jumps.
Here's my final snippet:

sbContainer is TScrollBox and NoScrCtrl is a control laying inside it which gets focus but we don't want it to be scrolled-in-view.

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;
划一舟意中人 2024-12-07 12:19:15

要从主窗体禁用滚动到视图行为,我使用了以下解决方案:(C++Builder)

bool __fastcall TMainForm::SetFocusedControl(TWinControl *Control) {
    LockWindowUpdate(Handle);
    int vpos = VertScrollBar->Position;
    int hpos = HorzScrollBar->Position;
    bool result = TForm::SetFocusedControl(Control);
    if (VertScrollBar->Position != vpos) {
        VertScrollBar->Position = vpos;
    }
    if (HorzScrollBar->Position != hpos) {
        HorzScrollBar->Position = hpos;
    }
    LockWindowUpdate(0);
    return result;
}

To disable scroll-into-view behavior from my main form, I used this solution: (C++Builder)

bool __fastcall TMainForm::SetFocusedControl(TWinControl *Control) {
    LockWindowUpdate(Handle);
    int vpos = VertScrollBar->Position;
    int hpos = HorzScrollBar->Position;
    bool result = TForm::SetFocusedControl(Control);
    if (VertScrollBar->Position != vpos) {
        VertScrollBar->Position = vpos;
    }
    if (HorzScrollBar->Position != hpos) {
        HorzScrollBar->Position = hpos;
    }
    LockWindowUpdate(0);
    return result;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文