Microsoft 365 Molette souris dans TextBox et ComboBox

ExcLnoob

XLDnaute Occasionnel
Bonjour le Forum,

Le sujet a déjà sans doute été évoqué mais j'y reviens tout de même...
Y-a-t-il un moyen de pouvoir utiliser la molette de la souris dans une combobox et une TextBox ?
J'ai trouvé plusieurs codes mais soit ça marche pour l'un et pas pour l'autre, soit cela fait beuguer mon Excel.
Avez-vous une solution light à me proposer ? Ou une solution stable et globale ?

Par avance merci pour votre aide!!
++
 

_Thierry

XLDnaute Barbatruc
Repose en paix
Re Bonsoir @ExcLnoob

Il faut faire appel à des API, et ce n'est pas le Top, d'une version de Windows à l'autre et je ne parle pas de Mac, ou de versions d'Office tu prends le risque que ca ne fonctionne plus, ou que tout simplement et comme tu dis très justement cela fasse beuguer ton Excel.

Il y a pléthore je pense de démo avec ça, sur ce forum.

Perso je ne conseille pas vraiment...

Bonne soirée
@+Thierry
 

Dudu2

XLDnaute Barbatruc
Bonsoir,
En effet, il y a ce code venu de l'espace et du tréfond des fonctions système mais attention, il interfère sur les autres applications, donc faut pas trop sortir d'Excel.
Après, si ça marche et ne perturbe pas ton environnement, pourquoi pas !
Car il faut dire qu'Office nous a un peu laissé ramer avec ces Scrolls ascenseurs des ListBoxes et ComboBoxes.
 

Pièces jointes

  • VBA Scroll Souris en ComboBox.xlsm
    33.4 KB · Affichages: 19

_Thierry

XLDnaute Barbatruc
Repose en paix
Bonsoir

Et oui, tous ces ActiveX standards des Userforms sont MS Form 6.0, datent, on dira, d'une vingtaine d'années à la louche !
C'est une volonté politique de MS de ne pas les avoir fait évoluer, car l'objectif est de tout simplement les supprimer...
Bon on a encore de la chance de les avoir encore même sous XL 2019, en 32 Bits.... Déjà en 64, il y en a pas mal qui ne passent plus (ListView par exemple)... J'ai entrevu que sur Team ça ne passe pas plus...

Donc il faut faire avec ce qu'on a et oui on rame on rame, ou alors on s'arrange comme dans ma réponse sur ComboBox liste déroulante "intuitive" où du coup on n'a plus vraiment besoin de scroller...

Bonne soirée
@+Thierry
 

Dudu2

XLDnaute Barbatruc
Bonsoir Staple1600,
Certes, fil récent, mais pas vraiment emballé / pesé direct en fichier. Donc reposte. Il y a des personnes qui n'ont pas la capacité de compiler les petits bouts et on ne peut pas leur en vouloir.
De toutes façons, ce sujet que tu cites était déjà présent dans un fil récent précédent.
Cordialement
 

ExcLnoob

XLDnaute Occasionnel
Bonsoir à tous et surtout merci pour vos réponses.

@Staple1600 mes plus plates excuses
Je me doutais que le sujet avait déja été évoqué comme je l'ai précisé dans la 2è ligne de mon premier message et les disucssions sur le sujet ne manque pas sur le/les forums.
Mon but n'était pas de créer un doublon mais simplement de savoir si il existait une solution simple et surtout stable.
Bien mal m'en a pris à ce que je vois. Je suis partisan du "vaut mieux poser la question que de se taire..." et ne suis pas du genre à poser des questions sans avoir chercher au préalable. Bref... Je ne le referais plus, promis!

@Dudu2 Merci pour ton support. J'ai retenté d'insérer ton code et mon système n'aime carrément pas... Je vais continuer à fouiller

@_Thierry Merci également pour ton support sur mes 2 topics, je vais bosser dessus.

Je ferme donc le sujet pour ne pas créer de "sur-fil"

Merci encore
 

patricktoulon

XLDnaute Barbatruc
Bonjour
Mon post visiblement étant invisible pour le demandeur voici un exemple simplifié (32/64 bits) seulement pour userform avec 4 listbox sans en activer une seule la molette fonctionne pour les 4
il suffit que la souris soit n'importe ou dans la listbox
code module hook
VB:
Option Explicit
#If VBA7 Then
    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 Any) As LongPtr
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "USER32" (ByVal hHook As LongPtr) As Long
    Private Declare PtrSafe Function SetWindowLong Lib "USER32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr

#Else
    Private Declare Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function FindWindowEx Lib "USER32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Private Declare Function GetWindowLong Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length 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 SetWindowLong Lib "USER32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

#End If



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 Long
' sera associé à la ListBox
Public CtrlHooked As Object
'
Private Function GetHookStruct(ByVal lParam As Long) As MSLLHOOKSTRUCT
    CopyMemory VarPtr(udtlParamStuct), lParam, LenB(udtlParamStuct)
    GetHookStruct = udtlParamStuct
End Function
Private Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'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 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, Optional ByVal FormName As String)
    Dim hWnd As Long
    ' active le hook s'il n'avait pas déjà été activé
    If plHooking < 1 Then
        hWnd = FindWindow(vbNullString, FormName)
        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)
    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
End Sub

code dans le userform avec 4 listbox
VB:
Private Sub ListBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    rouletambour ListBox1
End Sub
Private Sub ListBox2_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    rouletambour ListBox2
End Sub
Private Sub ListBox3_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    rouletambour ListBox3
End Sub
Private Sub ListBox4_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    rouletambour ListBox4
End Sub

Private Sub rouletambour(ListBox)
        If Not CtrlHooked Is Nothing Then If CtrlHooked.Name <> ListBox.Name Then UnHookMouse
         Call HookMouse(ListBox)
End Sub
Private Sub UserForm_Initialize()
    For i = 1 To 100
        ListBox1.AddItem i
        ListBox2.AddItem i * 100
        ListBox3.AddItem i / 100
        ListBox4.AddItem i * 1000
    Next
End Sub


Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    UnHookMouse
End Sub

démo
demo4.gif
 

Discussions similaires

Statistiques des forums

Discussions
312 108
Messages
2 085 369
Membres
102 875
dernier inscrit
Jimbo2374