Windows Forms: кнопка ctrl предотвращает прокрутку ListView с помощью колесика мыши

#c# #.net

#c# #.net

Вопрос:

Я хочу прокручивать список с помощью колеса мыши при нажатой кнопке Ctrl. Но, по-видимому, нажатие Ctrl изменяет поведение прокрутки: он останавливает прокрутку, возможно, пытается применить некоторую логику масштабирования, я не знаю. И я не могу узнать, как это переопределить. Пожалуйста, любая помощь или предложения?

Комментарии:

1. Что это за проект ?… Может быть, WinForms?

2. @Idle_Mind Извините, да, Windows forms

Ответ №1:

Решение для обеспечения прокрутки колесика мыши при удержании нажатой клавиши Ctrl — это прослушивание WndProc события и, в частности, обнаружение MOUSEWHEEL триггера, минимальный простой рабочий пример:

Список с WndProc переопределением

 class CtrlListBoxScroll : ListBox
{
    private const int WM_HSCROLL = 0x114;
    private const int WM_VSCROLL = 0x115;
    private const int WM_MOUSEWHEEL = 0x20A;

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_MOUSEWHEEL)
        {
            var scrollDirection = NativeMethods.GET_WHEEL_DELTA_WPARAM(m.WParam);
            // scrolling down
            if (this.TopIndex < this.Items.Count amp;amp; scrollDirection < 0)
            {
                this.TopIndex  = 1;
            }
            // scrolling up
            if (this.TopIndex > 0 amp;amp; scrollDirection > 0)
            {
                this.TopIndex -= 1;
            }
        }
    }
}
  

NativeMethods для чтения wParam и определения направления прокрутки

 internal static class NativeMethods
{
    internal static ushort HIWORD(IntPtr dwValue)
    {
        return (ushort)((((long)dwValue) >> 0x10) amp; 0xffff);
    }

    internal static ushort HIWORD(uint dwValue)
    {
        return (ushort)(dwValue >> 0x10);
    }

    internal static int GET_WHEEL_DELTA_WPARAM(IntPtr wParam)
    {
        return (short)HIWORD(wParam);
    }

    internal static int GET_WHEEL_DELTA_WPARAM(uint wParam)
    {
        return (short)HIWORD(wParam);
    }
}
  

Затем, наконец, протестируйте его

 private void Form1_Load(object sender, EventArgs e)
{
    var ctrlListBoxScroll = new CtrlListBoxScroll();
    ctrlListBoxScroll.Items.AddRange
    (
        new object[]
        {
            "hello", "scroll", "bar", "pressing", "ctrl", "to scroll",
            "this", "list", "box", "check", "ctrl", "key", "is", "held"
        }
    );
    this.Controls.Add(ctrlListBoxScroll);
}
  

Комментарии:

1. Неясный факт: аргумент, переданный OnMouseWheel(), на самом деле является обработанным MouseEventArgs . Что позволяет вам использовать аргумент e в переопределении метода и установить для его обрабатываемого свойства значение true . Вырезается много сложного кода.

2. referencesource.microsoft.com/#System . Windows. Forms / winforms/…

3. ListBox — это не то же самое, что ListView, где у вас могут быть разные представления, которые отображают объекты в СЕТКЕ (маленький значок, большой значок и т. Д.). Таким образом, код будет немного сложнее выяснить, как установить TopItem на основе количества элементов, отображаемых в каждой строке.