XL 2019 Molette Scroll sur ListBox

gg13

XLDnaute Occasionnel
Bonjour,

Je commence un nouveau projet pour lequel je devrai utiliser des ListBox et ComboBox.
Ces listes seront longues et je voudrais utiliser le scroll de la molette plutôt que les ascenseurs.

Après renseignement sur le site j’ai voulu utiliser ce post :
Mouse Wheel Hook (faire défiler le contenu d'une combobox/listbox avec la roulette)

Je galère depuis 2 jours et malgré plusieurs essais je n’arrive pas à intégrer ces différentes macros, plusieurs messages d’erreurs ….
Je ne comprends pas tout.
Si vous pouvez m’aider un peu je vous remercie d’avance.

Je joins le fichier exemple avec les listBox .

GG13
 

Pièces jointes

  • NBA1.3.xlsm
    37.6 KB · Affichages: 10

Dudu2

XLDnaute Barbatruc
@patricktoulon,

Mais bien sûr que j'avais compris ton bidule. Dans les divers codes de Hook de j'ai utilisé avant, j'avais bien vu ce Return à True mais ça ne me plaisait pas parce que pas en ligne avec la recommandation de MicroSoft.

Tu as trouvé la solution pour ta config et donc je l'ai implémentée pour que ça fonctionne chez toi aussi.
Elle n'est pas utile pour nous autres, mais apparemment sans préjudice.

apres tu essaie de me faire passer pour un "C..."
Allons allons ! Ce serait plutôt l'inverse, mais passons !

Ceci dit, ce n'est pas la fin car j'ai trouvé un autre cas d'erreur.
1667494365937.png

A suivre ...
 

Dudu2

XLDnaute Barbatruc
Cette erreur arrive lorsqu'on Scroll dans un Control de UserForm actif puis qu'on le ferme avec Alt + F4 puis qu'on essaie de scroller.

Par chance cette erreur est récupérée par un On Error général.
J'ai donc encore modifié le code pour en tenir compte.
 

Pièces jointes

  • VBA Scroll Souris en ListBox et ComboBox.xlsm
    70.8 KB · Affichages: 5

Dudu2

XLDnaute Barbatruc
au final tu a compris c'est l'essentiel
je me dis que j'y suis un peu pour quelque chose
Ah oui !
Quand je pense qu'il suffisait que tu dises:
Dans ma config, sur le WM_MOUSEWHEEL il faut mettre un retour de la fonction à True


Mais non, faut toujours que tu joues au devinettes avec des messages à rallonge et des copies d'écrans auquels on ne comprends plus rien.
 

Dudu2

XLDnaute Barbatruc
De toutes façons, je n'ai pas à "comprendre ta config" puisque je ne l'ai pas.
Il n'y avait rien "à comprendre" pour moi.

C'était à toi de comprendre qu'il fallait dire les choses en une phrase et pas en 50 messages blindés de trucs incompréhensibles, d'extraits de code, de GIF animés, etc...
 

Dudu2

XLDnaute Barbatruc
Bon, sinon je pense que ce code va pouvoir faire l'objet d'une ressource.

Et je pense que même si de nombreux codes sont disponibles pour le Scroll qui ont servi de point de départ à celui-ci, aucun n'arrive à gérer les Scroll de Controls ActiveX et UserForm des ListBox et ComboBox de manière transparente (pas de clic ou autre artifice nécessaire).

Donc on peut être fiers du résultat de ces nombreuses heures d'investigations, de tests et d'essais sur différentes configs.

1667496040899.png
 

patricktoulon

XLDnaute Barbatruc
tu plaisantes ou quoi
si tu écoutais ma fois on serait pas obligé de répéter de toute les manières possibles
des le debut je t'ai dis (dès les premières pages )

1° le callback
2° le callnext ne doit être appelé qu'en cas d'erreur( pour une raison ou une autre )

et puis c'est pas peine d'avoir donné des bouts de codes
le callback y était à chaque fois que je sache

à aucun moment tu ne m'a demandé pourquoi
je me suis senti obligé de te mettre le nez dessus de toute les manières que j'ai pu

quand je code une fonction qui va être en addressof je le fait tout de suite moi

VB:
private sub non_de_fonction(balblabla as balablabla,balbloblo as truc,....) as long
as long pour le return true ou false (1 ou 0)

et de suite après
apres

Code:
non_de_fonction=true
end sub

c'est un automatisme que tu dois avoir sans exception
te reste a coder entre les lignes et surtout de faire une gestion globale d'erreur et pas tout ce toin toin là
 

Usine à gaz

XLDnaute Barbatruc
Bonjour,

Je commence un nouveau projet pour lequel je devrai utiliser des ListBox et ComboBox.
Ces listes seront longues et je voudrais utiliser le scroll de la molette plutôt que les ascenseurs.

Après renseignement sur le site j’ai voulu utiliser ce post :
Mouse Wheel Hook (faire défiler le contenu d'une combobox/listbox avec la roulette)

Je galère depuis 2 jours et malgré plusieurs essais je n’arrive pas à intégrer ces différentes macros, plusieurs messages d’erreurs ….
Je ne comprends pas tout.
Si vous pouvez m’aider un peu je vous remercie d’avance.

Je joins le fichier exemple avec les listBox .

GG13
ça marche tout bien :)
 

Dudu2

XLDnaute Barbatruc
voila une gestion globale et c'est tout
C'est tout pour sécuriser des erreurs générales telles que celle-ci, oui.
Mais j'ai quand même dû traiter des erreurs particulières:
- Sur la sécurisation du Control Hooké à l'entrée (jamais eu de cas réel)
- Sur le set du .TopIndex (il y a des circonstances où on tombe dedans)
 

patricktoulon

XLDnaute Barbatruc
re
prendra tu le temps de me lire
et osera tu essayer (testé sur ta version 10 du fichier )
par avance mille excuse dès que j'ai une tronçonneuse dans les mains je coupe
VB:
'https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644986(v=vs.85)
Private Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Dim Bool As Boolean
    Dim ErrNumber As Long
    Dim Obj As Object
    Dim TopIndex As Long
    Dim DoNotCallNextHook As Boolean
    Static LastTimer As Single

    'Test validité du ControlHooked
    On Error GoTo gestion_d_erreur 'on fait une gestion globale
    'Set Obj = ControlHooked
    'ErrNumber = Err.Number
    'On Error GoTo 0

    'Le ControlHooked a disparu (UserForm fermé Alt + F4 par exemple)
    'If ErrNumber <> 0 Or ControlHooked Is Nothing Then
    'Call UnHookMouse
    'Else
    If nCode = HC_ACTION Then
        'If Int((Timer - LastTimer) * 100) >= 0 Then
         GoSub CheckMouseIsOverTheBox'd'office on attend pas de bouger
        'If wParam = WM_MOUSEMOVE Then    '???????????
            'DoNotCallNextHook = True

            'Either on WM_MOUSEMOVE or on WM_MOUSEWHEEL
          
           'GoSub CheckMouseIsOverTheBox ' ca je le met pas là je le met en exécution  d'office dans la proc
        'End If

        If wParam = WM_MOUSEWHEEL Then
            'DoNotCallNextHook = True
            LowLevelMouseProc = True 'le callback ici

            'Either on WM_MOUSEMOVE or on WM_MOUSEWHEEL
            'GoSub CheckMouseIsOverTheBox

            If Not plHooking = 0 Then

                With ControlHooked
                    'Is the Window still there ?
                    'TopIndex = .TopIndex

                    ' On Error Resume Next
                    '.TopIndex = 0
                    'ErrNumber = Err.Number
                    'On Error GoTo 0

                    'If ErrNumber <> 0 Then
                    '  Call UnHookMouse
                    ' Exit Function
                    'End If

                    '.TopIndex = TopIndex

                    'Moves the ScrollBar depending on the mouse wheel, Info is stored in lParam
                    If GetHookStruct(lParam).mouseData > 0 Then
                        If .TopIndex < ScrollStep Then .TopIndex = 0 Else .TopIndex = .TopIndex - ScrollStep
                    Else
                        .TopIndex = .TopIndex + ScrollStep
                    End If
                End With
            End If
        End If
        'End If
        'End If
    End If
    Exit Function
gestion_d_erreur:
    LowLevelMouseProc = CallNextHookEx(0&, nCode, wParam, ByVal lParam)

    Exit Function

CheckMouseIsOverTheBox:
    If Not ControlHooked Is Nothing Then 'j'ai du mal à comprendre comment dans la proc en addressof tu est besoins de tester le control
       ' On Error Resume Next
        Bool = MouseIsOverTheBox
        'ErrNumber = Err.Number
       ' On Error GoTo 0

        'Run time Error 57097: le résultat de l'appel à la fonction MouseMoveFunction() n'est pas significatif, on oublie !
        'If ErrNumber <> 57097 Then
            'If ErrNumber = 0 Then
                'The mouse is not anymore over the ControlHooked Object
              
              ' tu a une fonction booleene qui te dis si tu est toujours sur le control ou pas
               'et bien ca suffit pour unhooker selon le bool
                If Not Bool Then
                    Call UnHookMouse
                End If
            'End If
        'End If
    End If
    Return
End Function

démonstration
demo.gif
 

Dudu2

XLDnaute Barbatruc
Mais je prends le temps de lire quand tu n'en rajoutes pas de tous les cotés.
Mais je ne vais pas prendre ta fonction,; la mienne me convient.

Je ne crois pas avoir un code à rallonge:
VB:
Private Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Dim Obj As Object
    Dim DoNotCallNextHook As Boolean
    Static LastTimer As Single
 
    'Prevent Excel crash (e.g. Alt+F4 on UserForm with Hooked Control) and errors tracked here
    On Error Resume Next
 
    'Test validité du ControlHooked
    Set Obj = ControlHooked
 
    'Le ControlHooked a disparu ?
    If Err.Number <> 0 Or Obj Is Nothing Then
        Err.Clear
        Call UnHookMouse
    Else
        If nCode = HC_ACTION Then
            If Int((Timer - LastTimer) * 100) >= 0 Then
                If wParam = WM_MOUSEMOVE Then
                    'Check if the mouse is still on the Control
                    If Not MouseIsOverTheBox Then
                        Call UnHookMouse
                    End If
                End If
             
                If wParam = WM_MOUSEWHEEL Then
                    DoNotCallNextHook = True
                 
                    With ControlHooked
                        'Is the Window still there (.TopIndex in error) ?
                        Err.Clear
                     
                        'Moves the ScrollBar depending on the mouse wheel, Info is stored in lParam
                        If GetHookStruct(lParam).mouseData > 0 Then
                            If .TopIndex < ScrollStep Then .TopIndex = 0 Else .TopIndex = .TopIndex - ScrollStep
                        Else
                            .TopIndex = .TopIndex + ScrollStep
                        End If
                     
                        'Is the Window still there (.TopIndex in error) ?
                        If Err.Number <> 0 Then
                            Err.Clear
                            Call UnHookMouse
                            Exit Function
                        End If
                    End With
                End If
            End If
        End If
    End If

    If Not DoNotCallNextHook Then
        LowLevelMouseProc = CallNextHookEx(0&, nCode, wParam, ByVal lParam)
    Else
        LowLevelMouseProc = True
    End If
 
    LastTimer = Timer
    On Error GoTo 0
End Function
 

Dudu2

XLDnaute Barbatruc
D'ailleurs tu m'y fais penser, j'ai une erreur dans le test:
VB:
If Int((Timer - LastTimer) * 100) >= 0 Then
C'est:
VB:
If Int((Timer - LastTimer) * 100) > 0 Then
Je ne traite pas les messages qui arrivent en dessous d'1/100ème de seconde d'intervalle.
Ça sert à rien. Déjà c'est presque trop.

Et d'après mes traces, il y en a en pagaille.
 

Statistiques des forums

Discussions
314 667
Messages
2 111 706
Membres
111 264
dernier inscrit
Monnoye