关于c#:防止RichTextBox中的自动滚动

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

有人知道一种替代此行为的方法吗?

谢谢!


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

  • 备份初始选择
  • 取消控制的重点
  • 隐藏选择(通过Windows消息)
  • AppendText
  • 恢复初始选择
  • 取消隐藏选择
  • 重新调整控件

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

    [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在进行格式更改后滚动,这是唯一可行的方法。 乍一看似乎令人费解,但它有效:)


您可以看一下执行以下操作:

1
2

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

然后在附加日志数据的方法中(我在这里做一些假设),您可能会执行以下操作:

1
2
3
4
5
6
7

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甚至锁定击键,因此甚至无法键入。


SytS的解决方案存在一个问题,当"附加"某些文本时,滚动条将移动,从而使所选内容移至面板顶部。
一个解决方案是使用以下命令保存/恢复滚动位置:

1
2
3
4
5

    [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);

这个解决方案对我来说比较完整。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值