【问题标题】:Prevent Autoscrolling in RichTextBox防止 RichTextBox 中的自动滚动
【发布时间】:2010-10-12 05:40:47
【问题描述】:

我有一个使用 RichTextBox 控件实现的只读数据记录窗口。我希望能够禁用用户单击控件时发生的自动滚动,以便用户可以选择特定的日志进行复制/粘贴操作或其他操作。但是,一旦用户在 RichTextBox 中单击,它就会自动滚动到底部,这很困难。

有人知道一种方法来覆盖这种行为吗?

谢谢!

【问题讨论】:

    标签: c# winforms richtextbox


    【解决方案1】:

    你可以看看做这样的事情:

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr LockWindowUpdate(IntPtr Handle);
    

    然后在你的附加日志数据的方法中(我在这里做一些假设)你可能会做这样的事情:

    LockWindowUpdate(this.Handle);
    int pos = richTextBox1.SelectionStart;
    int len = richTextBox1.SelectionLength;
    richTextBox1.AppendText(yourText);
    richTextBox1.SelectionStart = pos;
    richTextBox1.SelectionLength = len;
    LockWindowUpdate(IntPtr.Zero);
    

    我做了一个带有计时器的小测试应用程序,它在richtextbox上进行了追加,它阻止了它的滚动,所以我可以进行文本选择。它存在一些位置问题并且并不完美,但也许它会帮助您找到自己的解决方案。

    一切顺利!

    【讨论】:

    • LockWindowUpdate 甚至会锁定击键,因此甚至无法输入。
    • -1 因为这是滥用LockWindowUpdate;它仅用于拖动操作,甚至不应该在现代 Windows 上使用。
    【解决方案2】:

    如果选择没有隐藏,RichTextBox 控件会自动滚动到当前选择。 RichTextBox.AppendText() 除了附加文本外,还修改当前选择,因此间接触发“自动滚动”行为。请注意,如果 RichTextBox.HideSelection 设置为 true,则当控件未获得焦点时,选择将被隐藏;这解释了您描述的行为,其中自动滚动仅在用户单击控件时发生。 (从而赋予它焦点) 为了防止这种情况,您需要在附加文本时执行以下操作:

    1. 备份初始选择
    2. 使控件失焦
    3. 隐藏选择(通过 Windows 消息)
    4. 追加文本
    5. 恢复初始选择
    6. 取消隐藏选择
    7. 重新调整控件的焦点

    您可能还想检查所选内容是否已经在文本末尾,如果是,则允许自动滚动行为 - 这实质上模拟了 Visual Studio 输出窗口的行为。例如:

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
        const int WM_USER = 0x400;
        const int EM_HIDESELECTION = WM_USER + 63;
    
        void OnAppend(string text)
        {
            bool focused = richTextBox1.Focused;
            //backup initial selection
            int selection = richTextBox1.SelectionStart;
            int length = richTextBox1.SelectionLength;
            //allow autoscroll if selection is at end of text
            bool autoscroll = (selection==richTextBox1.Text.Length);
    
            if (!autoscroll)
            {
                //shift focus from RichTextBox to some other control
                if (focused) textBox1.Focus();
                //hide selection
                SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 1, 0);
            }
    
            richTextBox1.AppendText(text);
    
            if (!autoscroll)
            {
                //restore initial selection
                richTextBox1.SelectionStart = selection;
                richTextBox1.SelectionLength = length;
                //unhide selection
                SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 0, 0);
                //restore focus to RichTextBox
                if(focused) richTextBox1.Focus();
            }
        }
    

    【讨论】:

    • 您的解决方案就像一个魅力!我尝试了很多其他方法来防止我的 RichTextBox 在进行格式更改后滚动,这是唯一有效的方法。起初看起来很复杂,但它确实有效:)
    【解决方案3】:

    SytS 的解决方案有一个问题,当“附加”某些文本时,滚动条会移动,以使选择转到面板顶部。 一个解决方案是保存/恢复滚动位置:

        [System.Runtime.InteropServices.DllImport("User32.dll")]
        extern static int GetScrollPos(IntPtr hWnd, int nBar);
    
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
    

    This solution 对我来说更完整。

    【讨论】:

      猜你喜欢
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 2016-05-08
      • 1970-01-01
      • 2018-06-21
      • 2020-09-20
      • 1970-01-01
      相关资源
      最近更新 更多