首页 > 解决方案 > 如何使用鼠标滚轮将 ListView 滚动一行而不是默认的三行?

问题描述

我有一个修改后的 ListView。当我使用鼠标滚轮滚动时,它滚动了三行。

我希望它使用鼠标滚轮一次滚动一行。

Public Class listviewEx
Inherits ListView
    Private Declare Function ShowScrollBar Lib "user32" (ByVal hwnd As IntPtr, ByVal wBar As Integer,
    ByVal bShow As Boolean) As Integer
    ' Constants
    Private Const SB_HORZ As Integer = 0

    Private Const WM_HSCROLL As Integer = &H114
    Private Const WM_VSCROLL As Integer = &H115

    Public Event Scroll As ScrollEventHandler


    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        ShowScrollBar(MyBase.Handle, SB_HORZ, False)
        If m.Msg = &H115 Then
            ' Trap WM_VSCROLL
        End If
    End Sub

    Public Sub New()
        MyBase.New()
        Me.SetStyle(ControlStyles.Opaque, True)
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.ResizeRedraw, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.SetStyle(ControlStyles.EnableNotifyMessage, True)
     End Sub
End Class

标签: vb.netwinformslistview

解决方案


您可以向 ListView 添加一个行为,使其滚动一行而不是默认的三行,使用Ctrl键(因为此修饰符通常用于更改这种行为)结合鼠标滚轮。

然后,您可以在未按下时具有标准的三行Ctrl滚动行为,并在按下时具有单行滚动行为。

覆盖 WndProc (正如您已经在做的那样),以处理WM_MOUSEWHEEL并验证Ctrl按键是否被按下,检查 WParam 的低位字是否为MK_CONTROL = &H08.

当它被按下时,确定增量是正数还是负数,并增加ListView.TopItem.Index返回的值,然后根据计算出的偏移量设置TopItem(添加最小/最大检查以避免溢出):

Imports System.Windows.Forms
Public Class ListViewEx
    Inherits ListView

    Private Const WM_MOUSEWHEEL As Integer = &H20A
    Private Const MK_CONTROL As Integer = &H8

    Public Sub New()
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)
        Select Case m.Msg
            Case WM_MOUSEWHEEL
                If Items.Count > 0 AndAlso (m.WParam.ToInt64() And &HFF) = MK_CONTROL Then
                    Dim offset = If((m.WParam.ToInt64() >> 16) > 0, -1, 1) + TopItem.Index
                    offset = Math.Max(Math.Min(offset, Items.Count - 1), 0)
                    TopItem = Items(offset)
                    m.Result = IntPtr.Zero
                End If
        End Select
    End Sub
End Class

推荐阅读