' Dans une feuille excel : ' Private Sub ComboBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Call HookMouse(ComboBox1, eSHEET) End Sub Private Sub ComboBox1_Click() ' pour valider le choix de la valeur par l'utilisateur, on va ailleurs Feuil1.Range("A1").Activate End Sub Private Sub ComboBox1_LostFocus() ' ' désactive le hook en sortant de la liste UnHookMouse End Sub Private Sub Worksheet_Deactivate() ' désactive le hook si on change de feuille, évitons les risques de crash UnHookMouse End Sub ' Ci-dessous, exemple sur une ListBox Private Sub ListBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Call HookMouse(ListBox1, eSHEET) End Sub Private Sub ListBox1_LostFocus() UnHookMouse End Sub
Option Explicit Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _ (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _ (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr) 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 LongPtr) As LongPtr Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" _ (ByVal hHook As LongPtr) As Long Public Enum OWNER eSHEET = 1 eUSERFORM = 2 End Enum Private Type POINTAPI X As Long Y As Long End Type Private Type MSLLHOOKSTRUCT pt As POINTAPI mouseData As Long flags As Long time As Long dwExtraInfo As Long End Type Private Const HC_ACTION = 0 Private Const WH_MOUSE_LL = 14 Private Const WM_MOUSEWHEEL = &H20A Private Const GWL_HINSTANCE = (-6) Private udtlParamStuct As MSLLHOOKSTRUCT ' permet de savoir si le hook est activé ou pas Public plHooking As LongPtr ' sera associé à votre ComboBox/ListBox Public CtrlHooked As Object ' Private Function GetHookStruct(ByVal lParam As LongPtr) As MSLLHOOKSTRUCT CopyMemory VarPtr(udtlParamStuct), lParam, LenB(udtlParamStuct) GetHookStruct = udtlParamStuct End Function Private Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr 'en cas de mouvement très rapide, 'évitons les crash en désactivant les erreurs On Error Resume Next If (nCode = HC_ACTION) Then If wParam = WM_MOUSEWHEEL Then LowLevelMouseProc = True With CtrlHooked ' déplace l'ascenseur en fonction de la molette ' l'info est stockée dans lParam If GetHookStruct(lParam).mouseData > 0 Then .TopIndex = .TopIndex - 3 Else .TopIndex = .TopIndex + 3 End If End With End If Exit Function End If LowLevelMouseProc = CallNextHookEx(0&, nCode, wParam, ByVal lParam) On Error GoTo 0 End Function Public Sub HookMouse(ByVal ControlToScroll As Object, ByVal SheetOrForm As OWNER, Optional ByVal FormName As String) Dim hWnd As LongPtr Dim hWnd_App As LongPtr Dim hWnd_Desk As LongPtr Dim hWnd_Sheet As LongPtr Dim hWnd_UserForm As LongPtr Const VBA_EXCEL_CLASSNAME = "XLMAIN" Const VBA_EXCELSHEET_CLASSNAME = "EXCEL7" Const VBA_EXCELWORKBOOK_CLASSNAME = "XLDESK" Const VBA_USERFORM_CLASSNAME = "ThunderDFrame" ' active le hook s'il n'avait pas déjà été activé If plHooking < 1 Then ' retourne l'handle d'excel hWnd_App = FindWindow(VBA_EXCEL_CLASSNAME, vbNullString) Select Case SheetOrForm Case eSHEET 'trouve son fils hWnd_Desk = FindWindowEx(hWnd_App, 0&, VBA_EXCELWORKBOOK_CLASSNAME, vbNullString) 'trouve celui de la feuille hWnd_Sheet = FindWindowEx(hWnd_Desk, 0&, VBA_EXCELSHEET_CLASSNAME, vbNullString) hWnd = hWnd_Sheet Case eUSERFORM 'trouve la UserForm hWnd_UserForm = FindWindowEx(hWnd_App, 0&, VBA_USERFORM_CLASSNAME, FormName) If hWnd_UserForm = 0 Then hWnd_UserForm = FindWindow(VBA_USERFORM_CLASSNAME, FormName) End If hWnd = hWnd_UserForm End Select Set CtrlHooked = ControlToScroll ' il n'y a pas de hInstance d'application, alors on utilise GetWindowLong pour obtenir l'hInstance plHooking = SetWindowsHookEx(WH_MOUSE_LL, AddressOf LowLevelMouseProc, GetWindowLong(hWnd, GWL_HINSTANCE), 0) Debug.Print Timer, "Hook ON" End If End Sub Public Sub UnHookMouse() ' désactive le hook s'il existe If plHooking <> 0 Then UnhookWindowsHookEx plHooking plHooking = 0 Set CtrlHooked = Nothing Debug.Print Timer, "Hook OFF" End If End Sub
Private Sub ComboBox1_Enter() Call HookMouse(Me.ComboBox1, eUSERFORM, Me.Name) End Sub Private Sub ComboBox1_Click() Me.cmdQuit.SetFocus UnHookMouse End Sub Private Sub ListBox1_Enter() Call HookMouse(Me.ListBox1, eUSERFORM, Me.Name) End Sub Private Sub ListBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) UnHookMouse End Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) UnHookMouse End Sub
On Error Resume Next If (nCode = HC_ACTION) Then If wParam = WM_MOUSEWHEEL Then LowLevelMouseProc = True With CtrlHooked ' déplace l'ascenseur en fonction de la molette ' l'info est stockée dans lParam If GetHookStruct(lParam).mouseData > 0 Then .TopIndex = .TopIndex - 3 Else .TopIndex = .TopIndex + 3 End If End With End If
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question