c # MouseWheel Scroll и RTB VScroll Event - PullRequest
0 голосов
/ 05 декабря 2011

Я немного смущен:

У нас есть приложение чата, которое требует НЕ прокручивать чат, если пользователь прокручивается вверх; и у нас есть класс scrollInfo, который дает нам возможность проверить, находится ли большой палец полосы прокрутки в нижней части полосы прокрутки, чтобы мы могли определить, следует ли нам прокручивать или нет.

К сожалению, есть много разных способов прокрутки чата. Можно использовать полосы прокрутки вверх / вниз, или большой палец полосы прокрутки, или просто прокрутить колесо мыши.

Однако, если используются стрелки вверх / вниз, у нас нет проблем.

И, если используется большой палец полосы прокрутки, событие VScroll запускается, но у нас нет способа определить, какое НАПРАВЛЕНИЕ перемещается большим пальцем или как проверить, удерживается ли оно в нажатом положении, без использования таймера для постоянного запроса состояние левой кнопки мыши.

И, наконец, если прокрутить колесико мыши, в то время как мы можем узнать, в каком направлении он движется, взглянув на свойство Delta, событие VScroll все еще срабатывает после обработки события колеса мыши. Таким образом, у нас, по сути, происходит дублирование прокрутки.

Мне нужна помощь с этим. Наше приложение чата выглядит следующим образом:

  • .NET 4.0 Приложение Windows Forms C #
  • Встроенный в Visual Studio 2010
  • * Вывод чата: * RichTextBox, который автоматически форматирует вводимый текст.

Вот пример нашей логики, которая просто не работает:

  1. Пользователь прокручивает вверх с помощью колесика мыши: когда приходят новые сообщения, они НЕ должны прокручивать окно вывода чата обратно вниз. Вместо этого, когда происходит событие прокрутки, он должен быть в состоянии определить местонахождение большого пальца прокрутки и сделать это определение.

  2. Пользователь прокручивает вверх с помощью большого пальца ScrollBar: происходит событие VScroll, которое проверяет, находится ли полоса прокрутки в нижней части поля прокрутки. И, если это так, он выполняет событие полной прокрутки, чтобы убедиться, что каретка всегда находится в конце поля прокрутки и скрыта (так что выходной сигнал чата ТОЛЬКО ЧТЕНИЕ не имеет фактического мигающего I луча).

  3. Пользователь прокручивает, используя полосы прокрутки вверх / вниз: работает просто отлично. (объяснять это не нужно, так как он уже работает).

Мне нужны некоторые пояснения, как я могу правильно проверить эти события?

-------- РЕДАКТИРОВАТЬ ДЛЯ УТОЧНЕНИЯ --------- Содержимое scrollInfo класса:

 internal class Scrollinfo
{
    internal const uint ObjidVscroll = 0xFFFFFFFB;

    [DllImport("user32.dll", SetLastError = true, EntryPoint = "GetScrollBarInfo")]
    private static extern int GetScrollBarInfo(IntPtr hWnd,
                                               uint idObject,
                                               ref Scrollbarinfo psbi);

    internal static bool CheckBottom(Control rtb, int postion)
    {
        var info = new Scrollbarinfo();
        info.CbSize = Marshal.SizeOf(info);

        var chk = GetScrollBarInfo(rtb.Handle,
                                   ObjidVscroll,
                                   ref info);
        if (chk == 0)
            GetScrollBarInfo(rtb.Handle,
                             ObjidVscroll,
                             ref info);


        bool isbottom = info.XyThumbBottom
                        >= (info.RcScrollBar.Bottom - info.RcScrollBar.Top - (info.DxyLineButton + 1));
        if (info.DxyLineButton <= 0) isbottom = true;
        if (info.XyThumbBottom <= 0) isbottom = true;
        return isbottom;
    }


}

internal struct Scrollbarinfo
{
    internal int CbSize;
    internal Rect RcScrollBar;
    internal int DxyLineButton;
    internal int XyThumbTop;
    internal int XyThumbBottom;
    internal int Reserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    internal int[] Rgstate;
}

internal struct Rect
{
    internal int Left;
    internal int Top;
    internal int Right;
    internal int Bottom;
}}

1 Ответ

0 голосов
/ 09 декабря 2011

Вы можете попробовать что-то вроде этого:

Обновите поле новым текстом для отображения, а затем найдите последнюю видимую строку, используя следующий код:

rtb.GetLineFromCharIndex(rtb.GetCharIndexFromPosition(new Point(rtb.Width, rtb.Height)));

Теперь в следующий раз, когда вам нужно будет поместить текст в RichTextBox, просто проверьте последнюю видимую строку, используя тот же код, что и выше.

Если новая последняя видимая строка меньше старой, это означает, что пользователь прокрутил вверх (или изменился размер RichTextBox). В любом случае вам просто нужно переместить курсор в конец текста, а затем вызвать метод RichTextBox.ScrollToCaret() для восстановления позиции.



Я также рекомендую вам взглянуть на следующее на сайте MSDN:

¹ Это можно использовать для установки положения каретки.

...