Sử dụng con lăn chuột trong listbox UserForm

Liên hệ QC

vu_tuan_manh_linh

linhvtm84@gmail.com
Tham gia
27/2/10
Bài viết
2,625
Được thích
1,893
Giới tính
Nam
Nghề nghiệp
Kỹ sư Kinh tế Xây dựng
Tôi đang sử dụng code sưu tầm trên diễn đàn về việc sử dụng con lăn chuột trong listbox userform. Tuy nhiên code chỉ chạy trên office 32bit. Nếu dùng office bản 64 bit thì bị lỗi đoạn code sau:
PHP:
Sub HookControlScroll(ByVal Ctl As MSForms.control)
    Dim lngAppInst As Long
    Dim hwndUnderCursor As Long
    Dim tPT As PointAPI
    GetCursorPos tPT
    hwndUnderCursor = WindowFromPoint(tPT.x, tPT.y)
    If mControlHwnd <> hwndUnderCursor Then
        UnhookControlScroll
        Set mCtl = Ctl
        mControlHwnd = hwndUnderCursor
        lngAppInst = GetWindowLong(mControlHwnd, GWL_HINSTANCE)
        If Not mbHook Then
            mLngMouseHook = _
            SetWindowsHookEx(WH_MOUSE_LL, _
'lỗi đúng chỗ này
'______________________
                             AddressOf MouseProc, _
'______________________
                             lngAppInst, 0)
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub
Tôi đã cố gắng tìm giải pháp trên các trang khác (VD https://stackoverflow.com/questions...serform-form-does-not-scroll-with-mouse-wheel) nhưng được trả lời là code này không chạy trên bản office 64 bit. Kính nhờ các thành viên giải quyết giúp vấn đề này. Xin cảm ơn!!
 
Sai đâu sửa đó . Trong hàm khai báo của SetWindowsHookEx chỗ tham số thứ 2 sửa lại kiểu Long thành LongPtr chơi.
 
Upvote 0
Sai đâu sửa đó . Trong hàm khai báo của SetWindowsHookEx chỗ tham số thứ 2 sửa lại kiểu Long thành LongPtr chơi.
Cảm ơn bạn! Tôi cũng đang đọc 1 bài khác trong diễn đàn nói về vấn đề này! Do không có kiến thức sâu nên tôi không hiểu 2 cái: win32 và win64, office32 và office64. sử dụng câu lệnh #If VBA7 là xác định win64 hay office64. Máy tôi sử dụng win64 và office 32 thì ok, nhưng máy win64 và office 64 thì không dùng được. Mong bạn giải thích giúp!
 
Upvote 0
Cảm ơn bạn! Tôi cũng đang đọc 1 bài khác trong diễn đàn nói về vấn đề này! Do không có kiến thức sâu nên tôi không hiểu 2 cái: win32 và win64, office32 và office64. sử dụng câu lệnh #If VBA7 là xác định win64 hay office64. Mong bạn giải thích giúp!

Chịu thua, mình chỉ biết sửa cho hết lỗi thôi ạ. Các vấn đề khác mình không biết. :(
 
Upvote 0
Code này xài cho Laptop vui nhỉ?
 
Upvote 0
ủa dựa vào yếu tố nào để kêu hpkhuong là anh, còn AutoReply là bạn nhỉ ? :confused:
 
Upvote 0
Sau một hồi loay hoay với #If VBA7, #If Win64, LongPtr thì cuối cùng cái lăn chuột nó cũng hoạt động, nhưng lăn chiều nào thì Scroll Bar nó cũng chỉ chạy có 1 chiều là đi từ dưới lên các bác ạ!
PHP:
'************************************************************************************
#If VBA7 Then
    Private Type PointAPI
            x As LongPtr
            y As LongPtr
End Type
    Private Type MOUSEHOOKSTRUCT
            pt As PointAPI
            hwnd As LongPtr
            wHitTestCode As LongPtr
            dwExtraInfo As LongPtr
    End Type
#Else
   Private Type PointAPI
        x As Long
        y As Long
End Type
    Private Type MOUSEHOOKSTRUCT
            pt As PointAPI
            hwnd As Long
            wHitTestCode As Long
            dwExtraInfo As Long
    End Type
#End If


'************************************************************************************
#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As LongPtr
#Else
    Private Declare Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long
#End If
'-------------
#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" _
            Alias "GetWindowLongPtrA" ( _
            ByVal hwnd As LongPtr, _
            ByVal nIndex As LongPtr) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" _
            Alias "GetWindowLongA" ( _
            ByVal hwnd As LongPtr, _
            ByVal nIndex As LongPtr) As LongPtr
    #End If
#Else
    Private Declare Function GetWindowLong Lib "user32.dll" _
        Alias "GetWindowLongA" ( _
        ByVal hwnd As Long, _
        ByVal nIndex As Long) As Long
#End If
'-------------
#If VBA7 Then
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
        Alias "SetWindowsHookExA" ( _
        ByVal idHook As LongPtr, _
        ByVal lpfn As LongPtr, _
        ByVal hMod As LongPtr, _
        ByVal dwThreadId As LongPtr) As LongPtr
#Else
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
    Alias "SetWindowsHookExA" ( _
        ByVal idHook As Long, _
        ByVal lpfn As Long, _
        ByVal hMod As Long, _
        ByVal dwThreadId As Long) As Long
#End If
'-----------
#If VBA7 Then
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _
        ByVal hHook As LongPtr, _
        ByVal ncode As LongPtr, _
        ByVal wParam As LongPtr, _
        ByRef lParam As Any) As LongPtr
#Else
    Private Declare Function CallNextHookEx Lib "user32" ( _
        ByVal hHook As Long, _
        ByVal ncode As Long, _
        ByVal wParam As Long, _
        ByRef lParam As Any) As Long
#End If
'-------------
#If VBA7 Then
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _
        ByVal hHook As LongPtr) As LongPtr
#Else
    Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
        ByVal hHook As Long) As Long
#End If
'------------
#If VBA7 Then
    Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
        ByVal xPoint As LongPtr, _
        ByVal yPoint As LongPtr) As LongPtr
#Else
    Private Declare Function WindowFromPoint Lib "user32" ( _
        ByVal xPoint As Long, _
        ByVal yPoint As Long) As Long
#End If
'-----------
#If VBA7 Then
    Private Declare PtrSafe Function GetCursorPos Lib "user32.dll" ( _
        ByRef lpPoint As PointAPI) As LongPtr
#Else
    Private Declare Function GetCursorPos Lib "user32.dll" ( _
        ByRef lpPoint As PointAPI) As Long
#End If
'************************************************************************************
#If VBA7 Then
    Private Const WH_MOUSE_LL As LongPtr = 14
    Private Const WM_MOUSEWHEEL As LongPtr = &H20A
    Private Const HC_ACTION As LongPtr = 0
    Private Const GWL_HINSTANCE As LongPtr = (-6)
    '************************************************************************************
    Private mLngMouseHook As LongPtr
    Private mControlHwnd As LongPtr
#Else
    Private Const WH_MOUSE_LL As Long = 14
    Private Const WM_MOUSEWHEEL As Long = &H20A
    Private Const HC_ACTION As Long = 0
    Private Const GWL_HINSTANCE As Long = (-6)
    '************************************************************************************
    Private mLngMouseHook As Long
    Private mControlHwnd As Long
#End If
Private mbHook As Boolean
Private mCtl As MSForms.control

'************************************************************************************
Sub HookControlScroll(ByVal Ctl As MSForms.control)
#If VBA7 Then
    Dim lngAppInst As LongPtr
    Dim hwndUnderCursor As LongPtr
#Else
    Dim lngAppInst As Long
    Dim hwndUnderCursor As Long
#End If
    Dim tPT As PointAPI
    GetCursorPos tPT
    hwndUnderCursor = WindowFromPoint(tPT.x, tPT.y)
    If mControlHwnd <> hwndUnderCursor Then
        UnhookControlScroll
        Set mCtl = Ctl
        mControlHwnd = hwndUnderCursor
        lngAppInst = GetWindowLong(mControlHwnd, GWL_HINSTANCE)
        If Not mbHook Then
            #If VBA7 Then
                mLngMouseHook = _
                SetWindowsHookEx(WH_MOUSE_LL, _
                             AddressOf MouseProcVBA7, _
                             lngAppInst, 0)
            #Else
                mLngMouseHook = _
                SetWindowsHookEx(WH_MOUSE_LL, _
                             AddressOf MouseProc, _
                             lngAppInst, 0)
            #End If
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub
'************************************************************************************
Sub UnhookControlScroll()
    If mbHook Then
        Set mCtl = Nothing
        UnhookWindowsHookEx mLngMouseHook
        mLngMouseHook = 0
        mControlHwnd = 0
        mbHook = False
    End If
End Sub
'************************************************************************************
Private Function MouseProc( _
        ByVal ncode As Long, _
        ByVal wParam As Long, _
        ByRef lParam As MOUSEHOOKSTRUCT) As Long
    On Error GoTo ErrorHandler
    Dim Index As Long
    If (ncode = HC_ACTION) Then
        If WindowFromPoint(lParam.pt.x, lParam.pt.y) = mControlHwnd Then
            If wParam = WM_MOUSEWHEEL Then
                MouseProc = True
                If lParam.hwnd > 0 Then
                    Index = -1
                Else
                    Index = 1
                End If
                Index = Index + mCtl.TopIndex
                If Index >= 0 Then
                    mCtl.TopIndex = Index
                End If
                Exit Function
            End If
        Else
            UnhookControlScroll
        End If
    End If
    MouseProc = CallNextHookEx( _
    mLngMouseHook, ncode, wParam, ByVal lParam)
    Exit Function
ErrorHandler:
    UnhookControlScroll
End Function
Private Function MouseProcVBA7( _
        ByVal ncode As LongPtr, _
        ByVal wParam As LongPtr, _
        ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
    On Error GoTo ErrorHandler
    Dim Index As LongPtr
    If (ncode = HC_ACTION) Then
        If WindowFromPoint(lParam.pt.x, lParam.pt.y) = mControlHwnd Then
            If wParam = WM_MOUSEWHEEL Then
                MouseProcVBA7 = True
                If lParam.hwnd > 0 Then
                    Index = -1
                Else
                    Index = 1
                End If
                Index = Index + mCtl.TopIndex
                If Index >= 0 Then
                    mCtl.TopIndex = Index
                End If
                Exit Function
            End If
        Else
            UnhookControlScroll
        End If
    End If
    MouseProcVBA7 = CallNextHookEx( _
    mLngMouseHook, ncode, wParam, ByVal lParam)
    Exit Function
ErrorHandler:
    UnhookControlScroll
End Function

Function Office32or64() As Long
Dim k As Long
Dim sPath As String
Dim aSubKeys(), vKey
Const cFind As String = "00FF1CE}"  ' note zeros and number 1
Const HKEY_LOCAL_MACHINE As Long = &H80000002
Dim objWMI As Object

    On Error GoTo errH
    Set objWMI = CreateObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

    sPath = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
    For k = 0 To 1
        objWMI.EnumKey HKEY_LOCAL_MACHINE, sPath, aSubKeys
        For Each vKey In aSubKeys
            If InStr(1, vKey, cFind) Then
                Select Case Mid$(vKey, 21, 1)
                Case "0": Office32or64 = 32
                Case "1": Office32or64 = 64
                End Select
                Debug.Print Mid$(vKey, 21, 1), vKey
                Exit Function
            End If
        Next
        ' this key will error in 32bit Windows
        sPath = "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
    Next
    Exit Function
errH:

End Function
 
Upvote 0
Sau một hồi loay hoay với #If VBA7, #If Win64, LongPtr thì cuối cùng cái lăn chuột nó cũng hoạt động, nhưng lăn chiều nào thì Scroll Bar nó cũng chỉ chạy có 1 chiều là đi từ dưới lên các bác ạ!
PHP:
'************************************************************************************
#If VBA7 Then
    Private Type PointAPI
            x As LongPtr
            y As LongPtr
End Type
    Private Type MOUSEHOOKSTRUCT
            pt As PointAPI
            hwnd As LongPtr
            wHitTestCode As LongPtr
            dwExtraInfo As LongPtr
    End Type
#Else
   Private Type PointAPI
        x As Long
        y As Long
End Type
    Private Type MOUSEHOOKSTRUCT
            pt As PointAPI
            hwnd As Long
            wHitTestCode As Long
            dwExtraInfo As Long
    End Type
#End If


'************************************************************************************
#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As LongPtr
#Else
    Private Declare Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long
#End If
'-------------
#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" _
            Alias "GetWindowLongPtrA" ( _
            ByVal hwnd As LongPtr, _
            ByVal nIndex As LongPtr) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" _
            Alias "GetWindowLongA" ( _
            ByVal hwnd As LongPtr, _
            ByVal nIndex As LongPtr) As LongPtr
    #End If
#Else
    Private Declare Function GetWindowLong Lib "user32.dll" _
        Alias "GetWindowLongA" ( _
        ByVal hwnd As Long, _
        ByVal nIndex As Long) As Long
#End If
'-------------
#If VBA7 Then
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
        Alias "SetWindowsHookExA" ( _
        ByVal idHook As LongPtr, _
        ByVal lpfn As LongPtr, _
        ByVal hMod As LongPtr, _
        ByVal dwThreadId As LongPtr) As LongPtr
#Else
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
    Alias "SetWindowsHookExA" ( _
        ByVal idHook As Long, _
        ByVal lpfn As Long, _
        ByVal hMod As Long, _
        ByVal dwThreadId As Long) As Long
#End If
'-----------
#If VBA7 Then
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _
        ByVal hHook As LongPtr, _
        ByVal ncode As LongPtr, _
        ByVal wParam As LongPtr, _
        ByRef lParam As Any) As LongPtr
#Else
    Private Declare Function CallNextHookEx Lib "user32" ( _
        ByVal hHook As Long, _
        ByVal ncode As Long, _
        ByVal wParam As Long, _
        ByRef lParam As Any) As Long
#End If
'-------------
#If VBA7 Then
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _
        ByVal hHook As LongPtr) As LongPtr
#Else
    Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
        ByVal hHook As Long) As Long
#End If
'------------
#If VBA7 Then
    Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
        ByVal xPoint As LongPtr, _
        ByVal yPoint As LongPtr) As LongPtr
#Else
    Private Declare Function WindowFromPoint Lib "user32" ( _
        ByVal xPoint As Long, _
        ByVal yPoint As Long) As Long
#End If
'-----------
#If VBA7 Then
    Private Declare PtrSafe Function GetCursorPos Lib "user32.dll" ( _
        ByRef lpPoint As PointAPI) As LongPtr
#Else
    Private Declare Function GetCursorPos Lib "user32.dll" ( _
        ByRef lpPoint As PointAPI) As Long
#End If
'************************************************************************************
#If VBA7 Then
    Private Const WH_MOUSE_LL As LongPtr = 14
    Private Const WM_MOUSEWHEEL As LongPtr = &H20A
    Private Const HC_ACTION As LongPtr = 0
    Private Const GWL_HINSTANCE As LongPtr = (-6)
    '************************************************************************************
    Private mLngMouseHook As LongPtr
    Private mControlHwnd As LongPtr
#Else
    Private Const WH_MOUSE_LL As Long = 14
    Private Const WM_MOUSEWHEEL As Long = &H20A
    Private Const HC_ACTION As Long = 0
    Private Const GWL_HINSTANCE As Long = (-6)
    '************************************************************************************
    Private mLngMouseHook As Long
    Private mControlHwnd As Long
#End If
Private mbHook As Boolean
Private mCtl As MSForms.control

'************************************************************************************
Sub HookControlScroll(ByVal Ctl As MSForms.control)
#If VBA7 Then
    Dim lngAppInst As LongPtr
    Dim hwndUnderCursor As LongPtr
#Else
    Dim lngAppInst As Long
    Dim hwndUnderCursor As Long
#End If
    Dim tPT As PointAPI
    GetCursorPos tPT
    hwndUnderCursor = WindowFromPoint(tPT.x, tPT.y)
    If mControlHwnd <> hwndUnderCursor Then
        UnhookControlScroll
        Set mCtl = Ctl
        mControlHwnd = hwndUnderCursor
        lngAppInst = GetWindowLong(mControlHwnd, GWL_HINSTANCE)
        If Not mbHook Then
            #If VBA7 Then
                mLngMouseHook = _
                SetWindowsHookEx(WH_MOUSE_LL, _
                             AddressOf MouseProcVBA7, _
                             lngAppInst, 0)
            #Else
                mLngMouseHook = _
                SetWindowsHookEx(WH_MOUSE_LL, _
                             AddressOf MouseProc, _
                             lngAppInst, 0)
            #End If
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub
'************************************************************************************
Sub UnhookControlScroll()
    If mbHook Then
        Set mCtl = Nothing
        UnhookWindowsHookEx mLngMouseHook
        mLngMouseHook = 0
        mControlHwnd = 0
        mbHook = False
    End If
End Sub
'************************************************************************************
Private Function MouseProc( _
        ByVal ncode As Long, _
        ByVal wParam As Long, _
        ByRef lParam As MOUSEHOOKSTRUCT) As Long
    On Error GoTo ErrorHandler
    Dim Index As Long
    If (ncode = HC_ACTION) Then
        If WindowFromPoint(lParam.pt.x, lParam.pt.y) = mControlHwnd Then
            If wParam = WM_MOUSEWHEEL Then
                MouseProc = True
                If lParam.hwnd > 0 Then
                    Index = -1
                Else
                    Index = 1
                End If
                Index = Index + mCtl.TopIndex
                If Index >= 0 Then
                    mCtl.TopIndex = Index
                End If
                Exit Function
            End If
        Else
            UnhookControlScroll
        End If
    End If
    MouseProc = CallNextHookEx( _
    mLngMouseHook, ncode, wParam, ByVal lParam)
    Exit Function
ErrorHandler:
    UnhookControlScroll
End Function
Private Function MouseProcVBA7( _
        ByVal ncode As LongPtr, _
        ByVal wParam As LongPtr, _
        ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
    On Error GoTo ErrorHandler
    Dim Index As LongPtr
    If (ncode = HC_ACTION) Then
        If WindowFromPoint(lParam.pt.x, lParam.pt.y) = mControlHwnd Then
            If wParam = WM_MOUSEWHEEL Then
                MouseProcVBA7 = True
                If lParam.hwnd > 0 Then
                    Index = -1
                Else
                    Index = 1
                End If
                Index = Index + mCtl.TopIndex
                If Index >= 0 Then
                    mCtl.TopIndex = Index
                End If
                Exit Function
            End If
        Else
            UnhookControlScroll
        End If
    End If
    MouseProcVBA7 = CallNextHookEx( _
    mLngMouseHook, ncode, wParam, ByVal lParam)
    Exit Function
ErrorHandler:
    UnhookControlScroll
End Function

Function Office32or64() As Long
Dim k As Long
Dim sPath As String
Dim aSubKeys(), vKey
Const cFind As String = "00FF1CE}"  ' note zeros and number 1
Const HKEY_LOCAL_MACHINE As Long = &H80000002
Dim objWMI As Object

    On Error GoTo errH
    Set objWMI = CreateObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

    sPath = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
    For k = 0 To 1
        objWMI.EnumKey HKEY_LOCAL_MACHINE, sPath, aSubKeys
        For Each vKey In aSubKeys
            If InStr(1, vKey, cFind) Then
                Select Case Mid$(vKey, 21, 1)
                Case "0": Office32or64 = 32
                Case "1": Office32or64 = 64
                End Select
                Debug.Print Mid$(vKey, 21, 1), vKey
                Exit Function
            End If
        Next
        ' this key will error in 32bit Windows
        sPath = "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
    Next
    Exit Function
errH:

End Function
Anh Linh đã xử lý được vụ này chưa ạ, em cũng dính cái này,. nếu được mong anh chia sẻ, cảm ơn
 
Upvote 0
Cảm ơn bạn! Tôi cũng đang đọc 1 bài khác trong diễn đàn nói về vấn đề này! Do không có kiến thức sâu nên tôi không hiểu 2 cái: win32 và win64, office32 và office64. sử dụng câu lệnh #If VBA7 là xác định win64 hay office64. Máy tôi sử dụng win64 và office 32 thì ok, nhưng máy win64 và office 64 thì không dùng được. Mong bạn giải thích giúp!
Có lẽ là cái này chăng: Tính tương thích ngược office 32 và 64
 
Upvote 0
Tôi đang sử dụng code sưu tầm trên diễn đàn về việc sử dụng con lăn chuột trong listbox userform. Tuy nhiên code chỉ chạy trên office 32bit. Nếu dùng office bản 64 bit thì bị lỗi đoạn code sau:
PHP:
Sub HookControlScroll(ByVal Ctl As MSForms.control)
    Dim lngAppInst As Long
    Dim hwndUnderCursor As Long
    Dim tPT As PointAPI
    GetCursorPos tPT
    hwndUnderCursor = WindowFromPoint(tPT.x, tPT.y)
    If mControlHwnd <> hwndUnderCursor Then
        UnhookControlScroll
        Set mCtl = Ctl
        mControlHwnd = hwndUnderCursor
        lngAppInst = GetWindowLong(mControlHwnd, GWL_HINSTANCE)
        If Not mbHook Then
            mLngMouseHook = _
            SetWindowsHookEx(WH_MOUSE_LL, _
'lỗi đúng chỗ này
'______________________
                             AddressOf MouseProc, _
'______________________
                             lngAppInst, 0)
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub
Tôi đã cố gắng tìm giải pháp trên các trang khác (VD https://stackoverflow.com/questions...serform-form-does-not-scroll-with-mouse-wheel) nhưng được trả lời là code này không chạy trên bản office 64 bit. Kính nhờ các thành viên giải quyết giúp vấn đề này. Xin cảm ơn!!
Trên Social MSND của microsoft cũng đang bàn tán xôn xao. Thấy có kết quả nên tôi copy code về đây luôn
Nguồn: Link
PHP:
(in the module)


Option Explicit

#If Win64 Then
    Private Type POINTAPI
       XY As LongLong
    End Type
#Else
    Private Type POINTAPI
           X As Long
           Y As Long
    End Type
#End If

Private Type MOUSEHOOKSTRUCT
    Pt As POINTAPI
    hWnd As Long
    wHitTestCode As Long
    dwExtraInfo As Long
End Type

#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As LongPtr
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                                            Alias "GetWindowLongPtrA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As LongPtr, _
                                                            ByVal hmod As LongPtr, _
                                                            ByVal dwThreadId As Long) As LongPtr
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As LongPtr, _
                                                           lParam As Any) As LongPtr
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr) As Long
    'Private Declare PtrSafe Function PostMessage Lib "user32.dll" _
    '                                         Alias "PostMessageA" ( _
    '                                                         ByVal hwnd As LongPtr, _
    '                                                         ByVal wMsg As Long, _
    '                                                         ByVal wParam As LongPtr, _
    '                                                         ByVal lParam As LongPtr) As Long
    #If Win64 Then
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal Point As LongLong) As LongPtr
    #Else
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function GetCursorPos Lib "user32" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#Else
    Private Declare Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As Long
    Private Declare Function GetWindowLong Lib "user32.dll" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As Long, _
                                                            ByVal nIndex As Long) As Long
    Private Declare Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As Long, _
                                                            ByVal hmod As Long, _
                                                            ByVal dwThreadId As Long) As Long
    Private Declare Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As Long, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As Long, _
                                                           lParam As Any) As Long
    Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As Long) As Long
    Private Declare Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As Long
    Private Declare Function GetCursorPos Lib "user32.dll" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#End If

Private Const WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const HC_ACTION As Long = 0
Private Const GWL_HINSTANCE As Long = (-6)
'Private Const WM_KEYDOWN As Long = &H100
'Private Const WM_KEYUP As Long = &H101
'Private Const VK_UP As Long = &H26
'Private Const VK_DOWN As Long = &H28
'Private Const WM_LBUTTONDOWN As Long = &H201
Dim n As Long
Private mCtl As Object
Private mbHook As Boolean
#If VBA7 Then
    Private mLngMouseHook As LongPtr
    Private mListBoxHwnd As LongPtr
#Else
    Private mLngMouseHook As Long
    Private mListBoxHwnd As Long
#End If

Sub HookListBoxScroll(frm As Object, ctl As Object)
    Dim tPT As POINTAPI
    #If VBA7 Then
        Dim lngAppInst As LongPtr
        Dim hwndUnderCursor As LongPtr
    #Else
        Dim lngAppInst As Long
        Dim hwndUnderCursor As Long
    #End If
    GetCursorPos tPT
    #If Win64 Then
        hwndUnderCursor = WindowFromPoint(tPT.XY)
    #Else
        hwndUnderCursor = WindowFromPoint(tPT.X, tPT.Y)
    #End If
  ' Đoạn này không cần thiết ---------------------------------------------------------
    If TypeOf ctl Is UserForm Then
        If Not frm Is ctl Then
               ctl.SetFocus
        End If
    Else
        If Not frm.ActiveControl Is ctl Then
             ctl.SetFocus
        End If
    End If
   '---------------------------------------------------------------------------------------
    If mListBoxHwnd <> hwndUnderCursor Then
        UnhookListBoxScroll
        Set mCtl = ctl
        mListBoxHwnd = hwndUnderCursor
        #If Win64 Then
            lngAppInst = GetWindowLongPtr(mListBoxHwnd, GWL_HINSTANCE)
        #Else
            lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE)
        #End If
        ' PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0&
        If Not mbHook Then
            mLngMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0&)
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub

Sub UnhookListBoxScroll()
    If mbHook Then
        Set mCtl = Nothing
        UnhookWindowsHookEx mLngMouseHook
        mLngMouseHook = 0
        mListBoxHwnd = 0
        mbHook = False
    End If
End Sub

#If VBA7 Then
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#Else
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#End If
        Dim idx As Long
        On Error GoTo errH
        If (nCode = HC_ACTION) Then
            #If Win64 Then
                If WindowFromPoint(lParam.Pt.XY) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                    Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #Else
                If WindowFromPoint(lParam.Pt.X, lParam.Pt.Y) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                        Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #End If
        End If
        MouseProc = CallNextHookEx(mLngMouseHook, nCode, wParam, ByVal lParam)
        Exit Function
errH:
        UnhookListBoxScroll
End Function

(in the Form)


Private Sub cmbbData_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
HookListBoxScroll Me, Me.cmbbData
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.cmbbData.AddItem s & i

        Next
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
        UnhookListBoxScroll
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Trên Social MSMD của microsoft cũng đang bàn tán xôn xao. Thấy có kết quả nên tôi copy code về đây luôn
Nguồn: Link
Mã:
(in the module)


Option Explicit

#If Win64 Then
    Private Type POINTAPI
       XY As LongLong
    End Type
#Else
    Private Type POINTAPI
           X As Long
           Y As Long
    End Type
#End If

Private Type MOUSEHOOKSTRUCT
    Pt As POINTAPI
    hWnd As Long
    wHitTestCode As Long
    dwExtraInfo As Long
End Type

#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As LongPtr
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                                            Alias "GetWindowLongPtrA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As LongPtr, _
                                                            ByVal hmod As LongPtr, _
                                                            ByVal dwThreadId As Long) As LongPtr
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As LongPtr, _
                                                           lParam As Any) As LongPtr
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr) As Long
    'Private Declare PtrSafe Function PostMessage Lib "user32.dll" _
    '                                         Alias "PostMessageA" ( _
    '                                                         ByVal hwnd As LongPtr, _
    '                                                         ByVal wMsg As Long, _
    '                                                         ByVal wParam As LongPtr, _
    '                                                         ByVal lParam As LongPtr) As Long
    #If Win64 Then
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal Point As LongLong) As LongPtr
    #Else
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function GetCursorPos Lib "user32" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#Else
    Private Declare Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As Long
    Private Declare Function GetWindowLong Lib "user32.dll" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As Long, _
                                                            ByVal nIndex As Long) As Long
    Private Declare Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As Long, _
                                                            ByVal hmod As Long, _
                                                            ByVal dwThreadId As Long) As Long
    Private Declare Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As Long, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As Long, _
                                                           lParam As Any) As Long
    Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As Long) As Long
    Private Declare Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As Long
    Private Declare Function GetCursorPos Lib "user32.dll" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#End If

Private Const WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const HC_ACTION As Long = 0
Private Const GWL_HINSTANCE As Long = (-6)
'Private Const WM_KEYDOWN As Long = &H100
'Private Const WM_KEYUP As Long = &H101
'Private Const VK_UP As Long = &H26
'Private Const VK_DOWN As Long = &H28
'Private Const WM_LBUTTONDOWN As Long = &H201
Dim n As Long
Private mCtl As Object
Private mbHook As Boolean
#If VBA7 Then
    Private mLngMouseHook As LongPtr
    Private mListBoxHwnd As LongPtr
#Else
    Private mLngMouseHook As Long
    Private mListBoxHwnd As Long
#End If

Sub HookListBoxScroll(frm As Object, ctl As Object)
    Dim tPT As POINTAPI
    #If VBA7 Then
        Dim lngAppInst As LongPtr
        Dim hwndUnderCursor As LongPtr
    #Else
        Dim lngAppInst As Long
        Dim hwndUnderCursor As Long
    #End If
    GetCursorPos tPT
    #If Win64 Then
        hwndUnderCursor = WindowFromPoint(tPT.XY)
    #Else
        hwndUnderCursor = WindowFromPoint(tPT.X, tPT.Y)
    #End If
    If TypeOf ctl Is UserForm Then
        If Not frm Is ctl Then
               ctl.SetFocus
        End If
    Else
        If Not frm.ActiveControl Is ctl Then
             ctl.SetFocus
        End If
    End If
    If mListBoxHwnd <> hwndUnderCursor Then
        UnhookListBoxScroll
        Set mCtl = ctl
        mListBoxHwnd = hwndUnderCursor
        #If Win64 Then
            lngAppInst = GetWindowLongPtr(mListBoxHwnd, GWL_HINSTANCE)
        #Else
            lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE)
        #End If
        ' PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0&
        If Not mbHook Then
            mLngMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0&)
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub

Sub UnhookListBoxScroll()
    If mbHook Then
        Set mCtl = Nothing
        UnhookWindowsHookEx mLngMouseHook
        mLngMouseHook = 0
        mListBoxHwnd = 0
        mbHook = False
    End If
End Sub

#If VBA7 Then
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#Else
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#End If
        Dim idx As Long
        On Error GoTo errH
        If (nCode = HC_ACTION) Then
            #If Win64 Then
                If WindowFromPoint(lParam.Pt.XY) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                    Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #Else
                If WindowFromPoint(lParam.Pt.X, lParam.Pt.Y) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                        Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #End If
        End If
        MouseProc = CallNextHookEx(mLngMouseHook, nCode, wParam, ByVal lParam)
        Exit Function
errH:
        UnhookListBoxScroll
End Function

(in the Form)


Private Sub cmbbData_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
HookListBoxScroll Me, Me.cmbbData
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.cmbbData.AddItem s & i

        Next
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
        UnhookListBoxScroll
End Sub
Cảm ơn bác, để em test thử rồi báo lại nhé
 
Upvote 0
Trên Social MSMD của microsoft cũng đang bàn tán xôn xao. Thấy có kết quả nên tôi copy code về đây luôn
Nguồn: Link
Mã:
(in the module)


Option Explicit

#If Win64 Then
    Private Type POINTAPI
       XY As LongLong
    End Type
#Else
    Private Type POINTAPI
           X As Long
           Y As Long
    End Type
#End If

Private Type MOUSEHOOKSTRUCT
    Pt As POINTAPI
    hWnd As Long
    wHitTestCode As Long
    dwExtraInfo As Long
End Type

#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As LongPtr
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                                            Alias "GetWindowLongPtrA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As LongPtr, _
                                                            ByVal nIndex As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As LongPtr, _
                                                            ByVal hmod As LongPtr, _
                                                            ByVal dwThreadId As Long) As LongPtr
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As LongPtr, _
                                                           lParam As Any) As LongPtr
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As LongPtr) As Long
    'Private Declare PtrSafe Function PostMessage Lib "user32.dll" _
    '                                         Alias "PostMessageA" ( _
    '                                                         ByVal hwnd As LongPtr, _
    '                                                         ByVal wMsg As Long, _
    '                                                         ByVal wParam As LongPtr, _
    '                                                         ByVal lParam As LongPtr) As Long
    #If Win64 Then
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal Point As LongLong) As LongPtr
    #Else
        Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As LongPtr
    #End If
    Private Declare PtrSafe Function GetCursorPos Lib "user32" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#Else
    Private Declare Function FindWindow Lib "user32" _
                                            Alias "FindWindowA" ( _
                                                            ByVal lpClassName As String, _
                                                            ByVal lpWindowName As String) As Long
    Private Declare Function GetWindowLong Lib "user32.dll" _
                                            Alias "GetWindowLongA" ( _
                                                            ByVal hWnd As Long, _
                                                            ByVal nIndex As Long) As Long
    Private Declare Function SetWindowsHookEx Lib "user32" _
                                            Alias "SetWindowsHookExA" ( _
                                                            ByVal idHook As Long, _
                                                            ByVal lpfn As Long, _
                                                            ByVal hmod As Long, _
                                                            ByVal dwThreadId As Long) As Long
    Private Declare Function CallNextHookEx Lib "user32" ( _
                                                            ByVal hHook As Long, _
                                                            ByVal nCode As Long, _
                                                            ByVal wParam As Long, _
                                                           lParam As Any) As Long
    Private Declare Function UnhookWindowsHookEx Lib "user32" ( _
                                                            ByVal hHook As Long) As Long
    Private Declare Function WindowFromPoint Lib "user32" ( _
                                                            ByVal xPoint As Long, _
                                                            ByVal yPoint As Long) As Long
    Private Declare Function GetCursorPos Lib "user32.dll" ( _
                                                            ByRef lpPoint As POINTAPI) As Long
#End If

Private Const WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const HC_ACTION As Long = 0
Private Const GWL_HINSTANCE As Long = (-6)
'Private Const WM_KEYDOWN As Long = &H100
'Private Const WM_KEYUP As Long = &H101
'Private Const VK_UP As Long = &H26
'Private Const VK_DOWN As Long = &H28
'Private Const WM_LBUTTONDOWN As Long = &H201
Dim n As Long
Private mCtl As Object
Private mbHook As Boolean
#If VBA7 Then
    Private mLngMouseHook As LongPtr
    Private mListBoxHwnd As LongPtr
#Else
    Private mLngMouseHook As Long
    Private mListBoxHwnd As Long
#End If

Sub HookListBoxScroll(frm As Object, ctl As Object)
    Dim tPT As POINTAPI
    #If VBA7 Then
        Dim lngAppInst As LongPtr
        Dim hwndUnderCursor As LongPtr
    #Else
        Dim lngAppInst As Long
        Dim hwndUnderCursor As Long
    #End If
    GetCursorPos tPT
    #If Win64 Then
        hwndUnderCursor = WindowFromPoint(tPT.XY)
    #Else
        hwndUnderCursor = WindowFromPoint(tPT.X, tPT.Y)
    #End If
    If TypeOf ctl Is UserForm Then
        If Not frm Is ctl Then
               ctl.SetFocus
        End If
    Else
        If Not frm.ActiveControl Is ctl Then
             ctl.SetFocus
        End If
    End If
    If mListBoxHwnd <> hwndUnderCursor Then
        UnhookListBoxScroll
        Set mCtl = ctl
        mListBoxHwnd = hwndUnderCursor
        #If Win64 Then
            lngAppInst = GetWindowLongPtr(mListBoxHwnd, GWL_HINSTANCE)
        #Else
            lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE)
        #End If
        ' PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0&
        If Not mbHook Then
            mLngMouseHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0&)
            mbHook = mLngMouseHook <> 0
        End If
    End If
End Sub

Sub UnhookListBoxScroll()
    If mbHook Then
        Set mCtl = Nothing
        UnhookWindowsHookEx mLngMouseHook
        mLngMouseHook = 0
        mListBoxHwnd = 0
        mbHook = False
    End If
End Sub

#If VBA7 Then
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#Else
Private Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr
#End If
        Dim idx As Long
        On Error GoTo errH
        If (nCode = HC_ACTION) Then
            #If Win64 Then
                If WindowFromPoint(lParam.Pt.XY) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                    Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #Else
                If WindowFromPoint(lParam.Pt.X, lParam.Pt.Y) = mListBoxHwnd Then
                    If wParam = WM_MOUSEWHEEL Then
                        MouseProc = True
'                        If lParam.hWnd > 0 Then
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0
'                        Else
'                            postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0
'                        End If
'                        postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0
                        If TypeOf mCtl Is Frame Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        ElseIf TypeOf mCtl Is UserForm Then
                            If lParam.hWnd > 0 Then idx = -10 Else idx = 10
                            idx = idx + mCtl.ScrollTop
                            If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then
                                mCtl.ScrollTop = idx
                            End If
                        Else
                            If lParam.hWnd > 0 Then idx = -1 Else idx = 1
                            idx = idx + mCtl.ListIndex
                            If idx >= 0 Then mCtl.ListIndex = idx
                        End If
                        Exit Function
                    End If
                Else
                    UnhookListBoxScroll
                End If
            #End If
        End If
        MouseProc = CallNextHookEx(mLngMouseHook, nCode, wParam, ByVal lParam)
        Exit Function
errH:
        UnhookListBoxScroll
End Function

(in the Form)


Private Sub cmbbData_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
HookListBoxScroll Me, Me.cmbbData
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.cmbbData.AddItem s & i

        Next
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
        UnhookListBoxScroll
End Sub
Em không hiểu sao phải bỏ đoạn code này mới chạy được (em đang test trên 64 bit):
Mã:
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.cmbbData.AddItem s & i

        Next
End Sub
 
Upvote 0
Em không hiểu sao phải bỏ đoạn code này mới chạy được (em đang test trên 64 bit):
Mã:
Private Sub UserForm_Initialize()
Dim i As Long
Dim s As String
        s = "this is line "
        For i = 1 To 50
                        Me.cmbbData.AddItem s & i

        Next
End Sub
Cái này là thêm Item bằng vòng lặp. Nếu bạn đã có một NameRange, Array thì bỏ vào
Me - nghĩa là Chính tôi, nếu Form tên gì thì Me đại diện Form đấy
cmbbData - đại diện cho ListBox / ComboBox / TextBox ...
Ví dụ: Me.cmbbData.List = Array(1,2,3,4,5)
FormName.cmbbData.List = Array(1,2,3,4,5)
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Đào lại bài cách đây 4 năm: một lỗi gặp phải với code scroll mouse listbox khi dùng office 2016 là hay bị đơ, out luôn excel, đành phải gỡ ra dùng 2010. Liệu có phải do ảnh hưởng của hiệu ứng chuyển tiếp cells của phiên bản 2016 không cả nhà???
 
Upvote 0
Web KT
Back
Top Bottom