【问题标题】:Get current scroll position from rich text box control?从富文本框控件获取当前滚动位置?
【发布时间】:2017-06-02 12:35:11
【问题描述】:

我在互联网上搜索过很多类似的问题,但我没有看到真正的答案。

我有一个包含大量文本的富文本框控件。它在此控件中有一些法律信息。默认情况下,“接受”按钮被禁用。如果 v-scroll bar 的位置在底部,我想检测滚动事件。如果它在底部,请启用该按钮。

如何检测当前的垂直滚动条位置?

谢谢!

编辑 我正在使用 WinForms (.Net 4.0)

【问题讨论】:

    标签: c# winforms .net-4.0 scrollbar richtextbox


    【解决方案1】:

    这应该让你接近你正在寻找的东西。这个类继承自 RichTextBox 并使用一些 pinvoking 来确定滚动位置。它添加了一个事件ScrolledToBottom,如果用户使用滚动条滚动或使用键盘,就会触发该事件。

    public class RTFScrolledBottom : RichTextBox {
      public event EventHandler ScrolledToBottom;
    
      private const int WM_VSCROLL = 0x115;
      private const int WM_MOUSEWHEEL = 0x20A;
      private const int WM_USER = 0x400;
      private const int SB_VERT = 1;
      private const int EM_SETSCROLLPOS = WM_USER + 222;
      private const int EM_GETSCROLLPOS = WM_USER + 221;
    
      [DllImport("user32.dll")]
      private static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);
    
      [DllImport("user32.dll")]
      private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam);
    
      public bool IsAtMaxScroll() {
        int minScroll;
        int maxScroll;
        GetScrollRange(this.Handle, SB_VERT, out minScroll, out maxScroll);
        Point rtfPoint = Point.Empty;
        SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref rtfPoint);
    
        return (rtfPoint.Y + this.ClientSize.Height >= maxScroll);
      }
    
      protected virtual void OnScrolledToBottom(EventArgs e) {
        if (ScrolledToBottom != null)
          ScrolledToBottom(this, e);
      }
    
      protected override void OnKeyUp(KeyEventArgs e) {
        if (IsAtMaxScroll())
          OnScrolledToBottom(EventArgs.Empty);
    
        base.OnKeyUp(e);
      }
    
      protected override void WndProc(ref Message m) {
        if (m.Msg == WM_VSCROLL || m.Msg == WM_MOUSEWHEEL) {
          if (IsAtMaxScroll())
            OnScrolledToBottom(EventArgs.Empty);
        }
    
        base.WndProc(ref m);
      }
    
    }
    

    这就是它的使用方法:

    public Form1() {
      InitializeComponent();
      rtfScrolledBottom1.ScrolledToBottom += rtfScrolledBottom1_ScrolledToBottom;
    }
    
    private void rtfScrolledBottom1_ScrolledToBottom(object sender, EventArgs e) {
      acceptButton.Enabled = true;
    }
    

    根据需要进行调整。

    【讨论】:

    • 请注意,当用户按住滚动条并移动它时,滚动位置不会更新。仅在释放鼠标按钮后。
    • 您能解释一下为什么我们需要在滚动位置添加this.ClientSize.Height 吗?为什么即使滚动在最底部,滚动位置也不等于maxScroll
    • @DmitryErokhin 好问题。 minScroll 和 maxScroll 给出了滚动距离的范围,但它被控件的大小所抵消,对于垂直滚动条来说,它是控件的高度。基本上,由于大小偏移,当存在滚动范围时,rtfPoint.Y 永远不会等于 maxScroll。
    【解决方案2】:

    以下在我的一个解决方案中效果很好:

    Point P = new Point(rtbDocument.Width, rtbDocument.Height);
    int CharIndex = rtbDocument.GetCharIndexFromPosition(P);
    
    if (rtbDocument.TextLength - 1 == CharIndex)
    {
       btnAccept.Enabled = true;
    }
    

    【讨论】:

      【解决方案3】:

      问题How to get scroll position for RichTextBox?可能会有所帮助,看看这个功能

         richTextBox1.GetPositionFromCharIndex(0);
      

      【讨论】:

        猜你喜欢
        • 2013-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多