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
Re,
J'ai voulu tester sur une configuration Portable 15" sous Windows 11 64Bits et Office 365 64Bits.
Effectivement en Affichage 125% cela ne fonctionne pas. Nous devons passer en 100%
 
patricktoulon, je ne sais pas si cela peut te servir mais avec UIAutomation on peut récupérer facilement la position sur l'écran d'un contrôle de formulaire. Voici un exemple pour ta procédure EmplacementControl (rect contient l'emplacement du contrôle)
VB:
Function EmplacementControl(obj As Object, Optional yy As Single = 0)
    If Not obj Is Nothing Then
        Dim oControl As IAccessible
        Dim oUIA As New CUIAutomation, UIA_Ctrl As IUIAutomationElement
        Dim rect As UIAutomationClient.tagRECT
        Set oControl = obj
        Set UIA_Ctrl = oUIA.ElementFromIAccessible(oControl, 0)
        rect = UIA_Ctrl.CurrentBoundingRectangle
        Dim Lft As Double, Ltop As Double, P As Object, PInsWidth As Double, PInsHeight As Double, tt As Double
        Dim K As Double, PPx, A, z
Ne pas oublier de cocher UIAutomationclient dans les références
 
ok je sais pourquoi en 125% ca colle pas
c'est le coeff que j'ai mis à 0.75 soit 100% en dpi 96
VB:
' fonction du calendar patricktoulon reconvertie
Function EmplacementControl(obj As Object, Optional yy As Single = 0)
    If Not obj Is Nothing Then
        Dim Lft As Double, Ltop As Double, P As Object, PInsWidth As Double, PInsHeight As Double, tt As Double
        Dim K As Double, PPx, A, z
        Lft = obj.Left ' Normalement Page, Frame ou UserForm
        Ltop = obj.Top
        Set P = obj.Parent
        Dim zoo#
        With ActiveWindow.Panes(1)
            zoo = .Parent.Zoom / 100
            PPx = Round(1 / ((.PointsToScreenPixelsY(7200 / zoo) - .PointsToScreenPixelsY(0)) / 7200), 2)
        End With
        Do
            PInsWidth = P.InsideWidth ' Le Page en est pourvu, mais pas le Multipage.
            PInsHeight = P.InsideHeight
            If TypeOf P Is MSForms.Page Then Set P = P.Parent ' Prend le Multipage, car le Page est sans positionnement.
            K = (P.Width - PInsWidth) / 2: Lft = (Lft + P.Left + K): Ltop = (Ltop + P.Top + P.Height - K - PInsHeight)
            If Not (TypeOf P Is MSForms.Frame Or TypeOf P Is MSForms.MultiPage) Then Exit Do
            Set P = P.Parent
            DoEvents
        Loop
        'pour la combobox on considère que le rectangle est le top à la position du curseur+3 left et right
        'il ne peut pas y avoir de raté
        If yy > 0 Then tt = Int(Ltop + obj.Height + yy) + 3 Else tt = Ltop + obj.Height
        EmplacementControl = Array(Lft / PPx, Ltop / PPx, (Lft + obj.Width) / PPx, tt / PPx)
    End If
End Function

merci pour vos retours
 
et pour les puriste on le prend avec l'api getdpiforwindow
PPx = 1 / (GetDpiForWindow(Application.hWnd) / 72)

j'en conclu qu'un large panel de confih on un retour positif
voila une belle trouvaille qui nous libère du hooking en addressof et donc des risques de crash excel
je met tout ça au propre peut être aussi dans un module histoire d'avoir un module dédié
mais j'ai assez l'idée d'avoir tout ça dans un formulaire comme je l'ai dit plus haut
si je veux livrer un formulaire et avoir tout intégré du henre le calendar c'est bien aussi
si vous avez des suggestions je prend

@jurassic pork je prend en compte ta proposition aussi mais j'ajoute l'activation automatique de uiautomationclient (comme pour ton vide pressepapier)
 

Pièces jointes

Hello,
Patricktoulon cela ne fonctionne pas sous Excel 2007 Win7 SP1 .
1 - Parce qu'il y a des erreurs de déclaration d' API quand ce n'est pas du VBA7 (excel 2007 = VBA 6.5) -> tu as laissé des longPtr
2 - Il semblerait que la fonction API GetDpiForWindow n'existait pas en Windows 7.
Finalement j'ai retrouvé un de tes codes ici qui permet d'avoir un objet IAccessible d'après les coordonnées Curseur ce qui permet de se passer de la fonction EmplacementControl :
Voici ce que cela donne :
1 - Pour la correction des déclarations :
VB:
Option Explicit
Private bLooping As Boolean
Private Type POINTAPI: x As Long: Y As Long: End Type
#If VBA7 Then
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    Private Declare PtrSafe Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As Msg, ByVal hWnd As LongPtr, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    Private Declare PtrSafe Function WaitMessage Lib "user32" () As Long
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Type Msg: hWnd As LongPtr: message As Long: wParam As LongPtr: lParam As LongPtr: time As Long: pt As POINTAPI: End Type
    #If Win64 Then
        Private Const NULL_PTR = 0
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal arg1 As LongPtr, ppacc As IAccessible, pvarChild As Variant) As Long
     #Else
        Private Const NULL_PTR = 0&
        Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
    #End If
    Private Function HiWord(Param As LongPtr) As Integer
        Call CopyMemory(HiWord, ByVal VarPtr(Param) + 2&, 2&)
    End Function
#Else
    Private Const NULL_PTR = 0&
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As Msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    Private Declare Function WaitMessage Lib "user32" () As Long
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Type Msg: hWnd As Long: message As Long: wParam As Long: lParam As Long: time As Long: pt As POINTAPI: End Type
    Private Declare Function AccessibleObjectFromPoint Lib "Oleacc" (ByVal lX As Long, ByVal lY As Long, ppacc As IAccessible, pvarChild As Variant) As Long
    Private Function HiWord(Param As Long) As Integer
        Call CopyMemory(HiWord, ByVal VarPtr(Param) + 2&, 2&)
    End Function
#End If

et pour la fonction MouseWeel ( que j'ai renommé MouseWheel)
Code:
Private Sub MouseWheel(control As Object, Optional yy As Single = 0)
    Const WHEEL_DELTA = 120&, WM_MOUSEWHEEL = &H20A, PM_NOREMOVE = &H0&
    Dim tMsg As Msg, lDelta As Integer, pos As POINTAPI, criter As Boolean, A
    Dim PosControl As IAccessible, MouseControl As IAccessible
    Set MouseControl = control
    Do
        GetCursorPos pos
        #If Win64 Then
            Dim lngPtr As LongPtr
            CopyMemory lngPtr, pos, LenB(pos)
            AccessibleObjectFromPoint lngPtr, PosControl, 0
        #Else
            AccessibleObjectFromPoint pos.x, pos.Y, PosControl, 0
        #End If
        If PosControl Is Nothing Then Exit Sub
        criter = (PosControl.accName = MouseControl.accName)
        If Not criter Then bLooping = False: Exit Sub
        bLooping = True
        Call WaitMessage
        If PeekMessage(tMsg, NULL_PTR, WM_MOUSEWHEEL, WM_MOUSEWHEEL, PM_NOREMOVE) Then
            lDelta = HiWord(tMsg.wParam)
            Select Case TypeName(control)
                Case "Frame"
                    If lDelta > 0& Then
                        tbx = "moins"
                        control.ScrollTop = Application.Max(control.ScrollTop - 8, 0)
                    Else
                        tbx = "plus"
                        control.ScrollTop = Application.Min(control.ScrollTop + 8, Frame1.ScrollHeight)
                    End If
                Case "ListBox", "ComboBox"
                    If lDelta > 0& Then
                        tbx = "moins"
                        On Error Resume Next
                        control.TopIndex = Application.Max(control.TopIndex - 1, 1)
                        On Error GoTo 0
                    Else
                        tbx = "plus"
                        On Error Resume Next
                        control.TopIndex = Application.Min(control.TopIndex + 1, control.ListCount - 1)
                        On Error GoTo 0
                    End If
            End Select
        End If 'End of PeekMessage
        DoEvents
    Loop Until bLooping = False
End Sub
En pièce jointe le classeur qui utilise IAccessible. Testé sous Excel 2016 32 bits , Excel 2021 64 bits Win11, Excel 2007 Win7 SP1.
Voici ce que cela donne avec Excel 2007 sous Windows 7 SP1 :


Ami calmant, J.P
 

Pièces jointes

Dernière édition:
Re Bonjour à tous
@jurassic pork
en effet mes déclarations étaient un peu bancales
feu POLUX (mon vieux pc portable HP) entant décédé je n'ai pas testé sur Windows 7
donc oui l'accesibleobjectfrompoint est une belle idée et presque évidente en soit 👍 👍

donc voila un fichier avec toute les versions Y compris (celle dans un module standard)

d'ailleurs j'ai ajouté le(pilote/copilote)
en effet pour certain controls qui n'ont pas le mouse move pour déclencher (comme le control scrollbar par exemple)
j'ai donc ajouté un argument optionnel a la sub mousewheel
utilisé dans cette démo en piece jointe

ou encore ici dans mon ImageMsoConverter to png
ou j'utilise un controls image transparent en tant que mask pour capter (avec y et y )un des 100 labels
le scroll est donc piloté par le control image et agit sur un control scrollbar qui lui me change les icones par tranche de 100 par 100 sur une liste de plus de 8500 IdMso
il ne bronche pas le truc

on ne peut pas dire que ce n'est pas véloce

et dire que j'ai découvert ça par hasard en jouant avec peekmessage et en me trompant de long dans les arguments
🤪🤣🤪

des fois la vie est belle

donc avant la rédaction de la ressource si vous avez des suggestions c'est le moment

Entre nous on est loin des usine a gaz avec le hooking mouseWheel

Merci a tous pour votre participation
Merci tout particulièrement à @jurassic pork👍

dorénavant vous avez le mouseWheell sans risque de crash Excel et sans UAG
 

Pièces jointes

Dernière édition:
donc avant la rédaction de la ressource si vous avez des suggestions c'est le moment
Pour le titre de ta ressource :
Utilisation roulette souris dans contrôles de formulaire
(on peut dire roulette ou molette c'est la même chose) (Version not AddressOf pas grand monde va comprendre à mettre dans la description)
- Mettre dans la description un gif animé qui montre l'utilisation dans différents types de contrôles de formulaire (comme dans ton classeur)
- Pour le classeur de démo mettre un nom assez explicite genre DémoRouletteSouris
 
re
je pense que je vais travailler avec iaccessible
j'ai donc ajouté le principe par control copilote (c'est un besoin que j'ai eu pour mon converter
mais j'ai ajouté aussi la prise en charge du scroll userform

@bonjour @Dudu2 je me demandais quand allais tu montrer le bout de ton nez 🤣
j'allais justement t'envoyer un message mp

pour récapitulatif ici
le projet est de se passer du hooking en adressof qui rend instable les applicatif (excel)
le principe etait donc au lieu du hook et callnexthook en looping en addressof qui parfois crash excel
récupérer le message de la souris avec un waitmessage et peekmessage dans le block type tmsg
dans un do/loop classic avec doevents
dans ce do loop toujours pareil capter la sortie du périmètre control
afin que ce do/loop s'arrête quand on sort

dans ce do loop il arrive parfois qu'il y ai des erreur de captage (mois souvent qu'en addressof )
mais c'est gérable par le on error resume next car gérer dans le stack de l'instance et non perdu dans les session en addressof

je finalise et poste la ressource
se sera une ressource en equipe avec @jurassic pork
@jurassic pork punaise tu a déterrer un post dvp de 2017
je voudrais le trouver je ne le trouverais pas 🤣🤣
edit :
(postée en attente de modé)
 
a ouais punaise l'usine a gaz le machin
non @Dudu2 j'ai fait un truc simple au départ
pour info j'ai des truc bizarre a l'affichage des listbox qui se doubles
c'est quoi ce truc


non si tu veux bien on va rester sur mon idée de depart
je regarderais plus tard ce qui provoque ça
 
- 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…