Autres tester le scroll de la frame

patricktoulon

XLDnaute Barbatruc
bonjour à tous
est ce que plusieurs d'entre vous pourraient tester le scroll de la frame avec la mollette sur des versions 365 2019 et 2021 svp
merci pour les retours
 

Pièces jointes

  • scrollexemple 2.xlsm
    25.8 KB · Affichages: 13

patricktoulon

XLDnaute Barbatruc
je viens d'essayer tout le code en entier sur un fichier vierge
demo2.gif


1716285247685.png
 

patricktoulon

XLDnaute Barbatruc
mon code corrigé par chatgpt
VB:
Option Explicit

Type POINTAPI
    X As Long
    Y As Long
End Type

#If Win64 Then
    Private Type MSLLHOOKSTRUCT
        pt As POINTAPI
        mouseData As Long
        flags As Long
        time As Long
        dwExtraInfo As LongPtr
    End Type
#Else
    Private Type MSLLHOOKSTRUCT
        pt As POINTAPI
        mouseData As Long
        flags As Long
        time As Long
        dwExtraInfo As Long
    End Type
#End If

#If Win64 Then
    Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As LongPtr)
    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
    Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As Long, lParam As LongPtr) As LongPtr
    Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As Long
    Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#Else
    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 GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#End If

Const HC_ACTION = 0
Const WH_MOUSE_LL = 14
Const WM_MOUSEWHEEL = &H20A

Public udtlParamStuct As MSLLHOOKSTRUCT

#If Win64 Then
    Public plHooking As LongPtr    ' permet de savoir si le hook est activé ou pas
#Else
    Public plHooking As Long       ' permet de savoir si le hook est activé ou pas
#End If

Public CtrlHooked As Object    ' sera associé à la ListBox
Public pos As POINTAPI
Public EpC As Variant

Sub rouletambour(obj)
    ' si ça n'a pas démarré, on démarre le hook
    If Not CtrlHooked Is Nothing Then
        If CtrlHooked.Name <> obj.Name Then UnHookMouse
    End If
    Call HookMouse(obj)
End Sub

Function GetHookStruct(ByVal lParam As LongPtr) As MSLLHOOKSTRUCT
    CopyMemory VarPtr(udtlParamStuct), lParam, LenB(udtlParamStuct)
    GetHookStruct = udtlParamStuct
End Function

#If Win64 Then
Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As LongPtr) As LongPtr
#Else
Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
    On Error Resume Next    ' en cas de mouvement très rapide, évitons les crashs en désactivant les erreurs
    Dim Criter As Boolean, i&
    GetCursorPos pos
    Criter = pos.X > EpC(0) And pos.X < EpC(2) And pos.Y > EpC(1) And pos.Y < EpC(3)    ' récupère les coordonnées en pixels (left/top/right/bottom du control)
    If Not Criter Then
        UnHookMouse
        Exit Function
    End If
    If (nCode = HC_ACTION) Then
        If wParam = WM_MOUSEWHEEL Then
            LowLevelMouseProc = True
            With CtrlHooked
                If GetHookStruct(lParam).mouseData > 0 Then
                    .ScrollTop = .ScrollTop - 45
                Else
                    .ScrollTop = .ScrollTop + 45
                End If
            End With
        End If
        Exit Function
    End If
    On Error GoTo 0
End Function

Public Sub HookMouse(ByVal ControlToScroll As Object, Optional ByVal FormName As String)
    If plHooking < 1 Then    ' active le hook s'il n'avait pas déjà été activé
        EpC = EmplacementControl(ControlToScroll)    ' on récupère le rectangle du contrôle par rapport à l'écran (pas du parent) du contrôle dans un array
        Set CtrlHooked = ControlToScroll
        plHooking = SetWindowsHookEx(WH_MOUSE_LL, AddressOf LowLevelMouseProc, 0, 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 If
End Sub

' fonction du calendar reconvertie
Function EmplacementControl(obj As Object)
    If Not obj Is Nothing Then
        Dim Lft As Double, Ltop As Double, ParentX As Object, ParentXInsWidth As Double, ParentXInsHeight As Double, K As Double, PPx, A, z
        Lft = obj.Left
        Ltop = obj.Top    ' Normalement Page, Frame ou UserForm
        Set ParentX = obj.Parent
        With CreateObject("WScript.Shell")
            PPx = 1 / (.RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager\LastLoadedDPI") / 72)
        End With
        Do
            ParentXInsWidth = ParentX.InsideWidth    ' Le Page en est pourvu, mais pas le Multipage
            ParentXInsHeight = ParentX.InsideHeight
            If TypeOf ParentX Is MSForms.Page Then Set ParentX = ParentX.Parent    ' Prend le Multipage, car le Page est sans positionnement
            K = (ParentX.Width - ParentXInsWidth) / 2
            Lft = (Lft + ParentX.Left + K)
            Ltop = (Ltop + ParentX.Top + ParentX.Height - K - ParentXInsHeight)
            If Not (TypeOf ParentX Is MSForms.Frame Or TypeOf ParentX Is MSForms.MultiPage) Then Exit Do
            Set ParentX = ParentX.Parent
        Loop
        EmplacementControl = Array(Lft / PPx, Ltop / PPx, (Lft + obj.Width) / PPx, (Ltop + obj.Height) / PPx)
    End If
End Function
 

patricktoulon

XLDnaute Barbatruc
alors j'ai trouvé en fait tout seul
en fait les private type il faut les mettre avant (enmême temps c'est evident) les argument des api s'en serve et comme on est en addressof y a in térêt que ça soit pré etabli et non post
la seule chose qu'il a changé c'est l'indentation et les deux long à la place des longptr dans une api
bon il m'a fait gagner du temps
bon ben voila je peux intégrer dans mon app Vba Indenter Interface 3.1
merci pour ton concours et ta patience c'est un peu toi qui m'a mis sur la voie
si @Dudu2 passe par la il va pourvoir mettre sa ressource a jour

ps :testé sur 2016 64 bits ça marche aussi
 

patricktoulon

XLDnaute Barbatruc
c'est normal tu a perdu le epc
mais l'ordre n'a pas été exécuté donc il continue son loops dans la level sauf que ctrlhooked n'est plus rien epc est vide il faudrait ajouter ca
if not isarray(epc) then unhookmouse:exit function
je vais agir pour la robustesse en sortant si epc ou ctrlhouked is nothing
bref je vais mettre des issue de secours partout ou je pourrais mettre
 

patricktoulon

XLDnaute Barbatruc
bon voila là on est bien paré
j'ai mis toute les sorties de secours possible dans criter
VB:
#If Win64 Then
Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As LongPtr) As LongPtr
#Else
Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
On Error Resume Next        ' en cas de mouvement très rapide, évitons les crashs en désactivant les erreurs
Dim Criter As Boolean, i&
GetCursorPos pos
Criter = plHooking <> 0
Criter = Criter & IsArray(EpC)
Criter = Criter & Not CtrlHooked Is Nothing
Criter = Criter & wParam <> 0
Criter = pos.X > EpC(0) And pos.X < EpC(2) And pos.Y > EpC(1) And pos.Y < EpC(3)        ' récupère les coordonnées en pixels (left/top/right/bottom du control)
If Not Criter Then UnHookMouse: Exit Function
If (nCode = HC_ACTION) Then
    If wParam = WM_MOUSEWHEEL Then
        LowLevelMouseProc = True
        With CtrlHooked
            If GetHookStruct(lParam).mouseData > 0 Then
                .ScrollTop = .ScrollTop - 45
            Else
                .ScrollTop = .ScrollTop + 45
            End If
        End With
    End If
    Exit Function
End If
If Err.numer Then Err.Clear: UnHookMouse
On Error GoTo 0
End Function

Bonjour @fanch55 bientot la 3.1 😁🥳🥳🥳🥳
là au moins comme je me tue a le dire à @Dudu2 on a quelque chose qui marche pour les 32/64 sans changer quoi que ce soit
reste plus qu'a remettre le select case typeof control
pour les listebox et textbox et combobox
quoi que pour le combobox je peaufine encore ma fonction du calendar que j'ai transformé pour quelle puisse capter le rectangle de la chid de la combo développée
mais bon ce n'est que de la broutille
 

Discussions similaires

Statistiques des forums

Discussions
315 090
Messages
2 116 104
Membres
112 661
dernier inscrit
ceucri