Запретить автопрокрутку в RichTextBox - PullRequest
10 голосов
/ 09 марта 2009

У меня есть окно регистрации данных только для чтения, которое я реализовал с помощью элемента управления RichTextBox. Я хотел бы иметь возможность отключить автоматическую прокрутку, которая происходит, когда пользователь щелкает элемент управления, чтобы пользователь мог выбрать определенный журнал для операций копирования / вставки или чего-либо еще. Однако, как только пользователь нажимает на RichTextBox, он автоматически прокручивается вниз, что затрудняет это.

Кто-нибудь знает способ переопределить это поведение?

Спасибо!

Ответы [ 3 ]

11 голосов
/ 18 апреля 2011

Элемент управления RichTextBox автоматически прокручивается до текущего выделения, если оно не скрыто. RichTextBox.AppendText (), помимо добавления текста, также изменяет текущее выделение и, таким образом, косвенно вызывает поведение «автопрокрутки». Обратите внимание, что если для RichTextBox.HideSelection установлено значение true, то выбор будет скрыт, когда элемент управления не в фокусе; это объясняет поведение, которое вы описали, когда автоматическая прокрутка происходит только тогда, когда пользователь щелкает элемент управления. (тем самым придавая этому фокус) Чтобы предотвратить это, вам нужно сделать следующее при добавлении текста:

  1. Резервное копирование начального выбора
  2. Расфокусировать управление
  3. Скрыть выбор (через сообщение Windows)
  4. AppendText
  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();
        }
    }
6 голосов
/ 09 марта 2009

Вы могли бы взглянуть на что-то вроде этого:

[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, и оно не давало ему прокручиваться, чтобы я мог делать выбор текста. У него есть некоторые позиционные проблемы и он не идеален, но, возможно, он поможет вам найти собственное решение.

Всего наилучшего!

1 голос
/ 15 сентября 2014

Решение 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);

Это решение для меня более полно.

...