Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

Autres toutes versions tester le scrool avec la roulette sans passer par un hooking en addressof

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

patricktoulon

XLDnaute Barbatruc
Bonjour a tous
la principal raison des crash excel quand on utilise le hooking de la souris pour avoir le mouse wheel(la roulette)
c'est que le looping avec le (CallnextHook)est asynchrone avec le captage du message de la souris
donc quand une erreur se produit(on va trop vite ou autre)
le looping lui continue parfois au moins une fois même en erreur
résultat comme on déplace le block type du message en mémoire ça crash

je vous propose de tester ceci
ici on va rester dans un do/loop vba classique et le message de la souris sera récupéré par un peekmessage
si il y a une erreur (du au message de la souris non conforme) normalement on a une erreur vba classique
et donc le do/loop est interrompu
donc pas de relance avec un message de la souris erroné donc pas de crash
Vous constaterez que j'augmente l'allocation de la mémoire aussi (64 bits double (longlong ou longPtr))(+2&)

d'autant plus que la dans cette démo je met tout dans le userform
ce qui n'est pas possible avec un code de hooking bien entendu
et ça peut avoir un avantage lorsque l'on veut distribuer un interface(userform) sans devoir l'accompagner de x modules

toujours pareil pour déterminer le rectangle je me sert de ma fonction perso du calendar que j'ai modifié pour ce besoins
donc testez et si ça fonctionne je ferais une ressource au propre

merci d'avance pour votre participation

j'en connais un qui vas ouvrir grand les yeux 🤣

Patrick
 

Pièces jointes

Solution
Bonjour @jurassic pork , @Dudu2 , @Nathe
j'ai mis le controlrelease en optionnel dans la démo (fonctionne aussi dans userform)
j'en ai profité pour mettre un multipage
et dans la page 1 du multipage j'ai mi un label violet
et c'est lui qui pilote le scroll de la page
comme ca on peut mettre un fond sur chaque page vu que ce control n'a pas de propertie backcolor
bien évidemment j'ai ajouté le textbox
dans cette démo donc on a le controlrelease optionnel
et le scroll piloté par un autre control
voila comme ça on est au même niveau que la V 3.0 avec iaccessible (All control working)

patrick
P.S. J'en rigole encore du truc de @jurassic pork !
C'est étrange, j'entends presque la voix de ces acteurs formidables prononcer ces paroles.
Hello,
voici la version vidéo de mon post #557 (les voix par I.A, durée 14 secondes) :
Rappel du casting (post de crocrocro) :

Monsieur Fernand : Lino Ventura - Dudu2
Raoul Volfoni : Bernard Blier - patricktoulon

Pour afficher ce contenu, nous aurons besoin de votre consentement pour définir des cookies tiers.
Pour plus d'informations, consultez notre page sur les cookies.

Ami calmant, J.P
 
par exemple

VB:
Private Type TAG_MOUSEINPUT
    dx As Long
    dy As Long
    mouseData As Long
    dwFlags As Long
    time As Long
    dwExtraInfo As LongPtr
End Type

Private Type MOUSE_INPUT
    type As Long
    mi As TAG_MOUSEINPUT
End Type


Private Sub ClickAtPosition(ByVal X As Long, ByVal Y As Long, Optional ByVal ScrollLines As Long = 1&)

    Const MOUSEEVENTF_LEFTDOWN = &H2, MOUSEEVENTF_LEFTUP = &H4
    ReDim uInput(2&) As MOUSE_INPUT
    Dim uCurPos As POINTAPI, i As Long

    GetCursorPos uCurPos
    ShowCursor 0&
    'SetCursorPos X, Y
    For i = 0& To ScrollLines - 1&
        With uInput(0&)
            .type = 0&
            .mi.dx = X
            .mi.dy = Y
            .mi.mouseData = 0&
            .mi.dwFlags =déplacer la souris +  MOUSEEVENTF_LEFTDOWN
        End With
        With uInput(1&)
            .type = 0&
            .mi.dx = X
            .mi.dy = Y
            .mi.mouseData = 0&
            .mi.dwFlags = MOUSEEVENTF_LEFTUP
        End With
        Call SendInput(2&, uInput(0&), LenB(uInput(0&)))
    Next i
    SetCursorPos uCurPos.X, uCurPos.Y
    ShowCursor -1&

End Sub

1° y a t il un moyen d'envoyer le message de déplacement en plus du click

2° Call SendInput(2&, uInput(0&), LenB(uInput(0&)))
le nombre 2& c'est pour dire les deux (input(0) et input(1)?
 

Bonjour Monsieurs @Dudu2 /

jurassic pork

Merci énormément pour votre travail

J'ai créé des contrôles (notamment des combobox ) de manière dynamique via un module de classe : grace à leur tag

QUESTIONS :
1. Est-il possible de scroller chaque combobox en fonction de son .tag ?
2. Ou bien scroller tous les combobox sans exception 'Sans tenir compte de son .Name) ?
3. Comment personnaliser l'apparence des scrollbar vertical genre comme celui d'un ListView et non celui la forme carré Standard des ListBox ?
Merci d'avance !!!
 

Pièces jointes

  • Create_Invoice.xlsm
    Create_Invoice.xlsm
    102.5 KB · Affichages: 3
  • Capture d'écran 2025-03-30 144707.png
    38.9 KB · Affichages: 6
  • Capture d'écran 2025-03-30 144644.png
    24 KB · Affichages: 7
  • Capture d'écran 2025-03-30 144609.png
    20.8 KB · Affichages: 6
Dernière édition:
Bonjour Pratricktoulon

Alors êtes vous disponible pour répondre à mes questions en utilisant votre méthode "hors hooking et divers moteur de scroll avec le lparam ou delta" SVP

Moi qu'importe la méthode ou l'approche j'admire vos différentes contributions

<je cherches que des solutions à mes questions

Peu importe de qui ça vient ..Nous gagnons tous en challenge au final

Cordialement !!!
 
re
pour répondre a ta question ou c'est possible et cela avec une méthode ou une autre
et cela sans besoins de connaitre le nom de la combobox
il suffit d'instancier des classe avec un module classe gérant les event des combobox
et d'appeler le scroll (methode ou l'autre) a partir de cet event dans la classe
malheureusement des l'ouverture de ton fichier j'ai une erreur de "chemin inrouvable"

cela dit la question n'est pas vraiment la possibilité de scroller mais de pouvoir piloter le scroll de plusieurs combobox

je t'ai donc fait un exemple vite fait comme ça
: dans le userform j'ai 6 comboboxs
pour identifier les combobox a intégrer dans la la classe je les ai tagué avec "x"
j'ai ajouté un module classe (on ne peut plus simple)qui va gérer l'event mouse move pour déclencher la capacité du scroll
au départ dans le activate du userform e donne un exemple (on ne peut plus simple encore )de classer X combobox )

a l'affichage toute les combobox ont le scroll avec la roulette

voila c'est assez simple et vu le code fourni dans ton fichier je pense que c'est a ta portée
si c'est pas le cas il faudra ouvrir une discussion sur ton vrai problème qui est l'intégration de control dans un module classe gérant les events

A noter que dans cet exemple les combobox existent déjà et il est possible de faire la même chose avec des combobox créées dynamiquement l'intégration se ferait alors lors de leur création
et avec une collection on peut le faire a tout moment
voila
patrick
 

Pièces jointes

Merci énormément pour tout. mais ça ne fonctionne pas

 
Dernière édition:
Bonjour à tous voici une belle découverte
qui va rendre obsolète( tout du moins pour les userform ) toutes méthodes de scrolling vu a ce jour
en test et expérience pour le moment
les frames et listbox pas de problème (ne fonctionne pas pour les combobox mais je cherche )

en gros le principe
instancier un events object InkCollector
activer son scroll
et se servir de son event "IC_MouseWheeL "scroller les autres controls
VB:
Private WithEvents IC As MSINKAUTLib.InkCollector
Public mycontrol As Control
Dim handle As Long

Private Sub UserForm_Activate()
    ListBox1.List = Evaluate("row(1:30)")
    ComboBox1.List = Evaluate("row(1:30)")
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    'stop the scrolling when you leaves control
    ' destruction of object IC
    Set IC = Nothing
End Sub

'I CAN TAKE A FRAME1 HANDLE FOR ALL CONTROLS
'THE HANDLE IS JUST A REFERENCE  FOR THE IC OBJECT
'handle = Frame1.[_GethWnd]


Private Sub ComboBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    handle = Frame1.[_GethWnd] 'it take a handle of frame because combobox has not disponible handle
    Set mycontrol = ComboBox1
    mycontrol.SetFocus
    SetupMouseWheel
End Sub

Private Sub Frame1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    handle = Frame1.[_GethWnd]
    Set mycontrol = Frame1
    mycontrol.SetFocus
    SetupMouseWheel
End Sub

Private Sub ListBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    handle = Frame1.[_GethWnd] 'handle = ListBox1.[_GethWnd]' this two can work
    Set mycontrol = ListBox1
    mycontrol.SetFocus
    SetupMouseWheel
End Sub

Private Sub SetupMouseWheel()
    Set IC = New MSINKAUTLib.InkCollector
    With IC
        .hwnd = handle ' The InkCollector requires an 'anchor' hWnd
        .SetEventInterest ICEI_MouseWheel, True ' This sets event that you want to listen for
        .MousePointer = IMP_Arrow ' If this is not set, the mouse pointer disappears
        .DynamicRendering = False ' I suggest turning this off
        .DefaultDrawingAttributes.Transparency = 255 ' And making the drawing fullly transparent
        .Enabled = True ' This must be set last
    End With
End Sub

Private Sub IC_MouseWheel(ByVal Button As MSINKAUTLib.InkMouseButton, ByVal Shift As MSINKAUTLib.InkShiftKeyModifierFlags, ByVal Delta As Long, ByVal X As Long, ByVal Y As Long, Cancel As Boolean)
    Select Case True
        Case TypeOf mycontrol Is Frame
            If Delta > 0 Then
                Frame1.ScrollTop = Application.Max(0, Frame1.ScrollTop - 5)
            Else
                Frame1.ScrollTop = Application.Min(Frame1.ScrollHeight, Frame1.ScrollTop + 5)
            End If
          
        Case TypeName(mycontrol) = "ListBox"
            If Delta > 0 Then
                ListBox1.TopIndex = Application.Max(ListBox1.TopIndex - 1, 0)
            Else
                ListBox1.TopIndex = Application.Min(ListBox1.TopIndex + 1, ListBox1.ListCount - 1)
            End If
          
        Case TypeName(mycontrol) = "ComboBox"
            If Delta > 0 Then
                ComboBox1.TopIndex = Application.Max(ComboBox1.TopIndex - 1, 0)
            Else
                ComboBox1.TopIndex = Application.Min(ComboBox1.TopIndex + 1, ComboBox1.ListCount - 1)
            End If
    End Select
End Sub

En tout cas c'est très prometteur
pas de looping en adressof ou pas
l'event est en interne donc pas de vba tournant en arrière plan
 
Hello,
et dans une feuille c'est possible ? en prenant le hwnd du panneau de la feuille ?
Ami calmant, J.P
 
Bonjour @jurassic pork
je sais pas je n'ai pas testé
mais dans tout les cas ça peut être une alternative sérieuse pour les frames et listbox dans un userform (ce qui est le besoin le plus fréquent)
sans être obligé de mettre un module de fou

il n'y a pas de charge vba si ce n'est pendant les coup de roulette et ça ça n'a pas de prix
du coup j'ai un peu restructurer le code

VB:
Private WithEvents IC As MSINKAUTLib.InkCollector
Public mycontrol As Control

'creation de l'object InkCollertor pour piloter le scroll
Private Sub SetupMouseWheel(Ctrl As Control)
    Set IC = New MSINKAUTLib.InkCollector
    Ctrl.SetFocus
    Set mycontrol = Ctrl
    With IC
        .hwnd = Ctrl.[_GethWnd] ' The InkCollector requires an 'anchor' hWnd
        .SetEventInterest ICEI_MouseWheel, True ' This sets event that you want to listen for
        .MousePointer = IMP_Arrow ' If this is not set, the mouse pointer disappears
        .DynamicRendering = False ' I suggest turning this off
        .DefaultDrawingAttributes.Transparency = 255 ' And making the drawing fullly transparent
        .Enabled = True ' This must be set last
    End With
End Sub

Private Sub UserForm_Activate()
    ListBox1.List = Evaluate("row(1:30)")
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    'stop the scrolling when you leaves control
    ' destruction of object IC
    Set IC = Nothing
    'provisoire  je vais lui ajouter la fonction rectangle sans api pour sortir
End Sub


Private Sub Frame1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    SetupMouseWheel Frame1
End Sub

Private Sub ListBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    SetupMouseWheel ListBox1
End Sub


Private Sub IC_MouseWheel(ByVal Button As MSINKAUTLib.InkMouseButton, ByVal Shift As MSINKAUTLib.InkShiftKeyModifierFlags, ByVal Delta As Long, ByVal X As Long, ByVal Y As Long, Cancel As Boolean)
    Select Case True
        Case TypeOf mycontrol Is Frame
            If Delta > 0 Then
                Frame1.ScrollTop = Application.Max(0, Frame1.ScrollTop - 5)
            Else
                Frame1.ScrollTop = Application.Min(Frame1.ScrollHeight, Frame1.ScrollTop + 5)
            End If
            
        Case TypeName(mycontrol) = "ListBox"
            If Delta > 0 Then
                ListBox1.TopIndex = Application.Max(ListBox1.TopIndex - 1, 0)
            Else
                ListBox1.TopIndex = Application.Min(ListBox1.TopIndex + 1, ListBox1.ListCount - 1)
            End If
    End Select
End Sub
le moteur de scroll c'est la création de l'object et son event c'est tout
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

P
Réponses
1
Affichages
834
P
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…