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

patricktoulon

XLDnaute Barbatruc
re
je viens de rentrer et j'ai testé ben pour la combo c'est mort
quand on sort le scroll n'est pas arrêté
démonstration
demo.gif
 

Dudu2

XLDnaute Barbatruc
quand on sort le scroll n'est pas arrêté

ben pour la combo c'est mort
C'est mort, pas tant que ça, te réjouis pas trop vite :cool: .
Cette question je l'ai déjà abordée, c'est le tout petit prix à payer pour une gestion SIMPLE.
Au prochain clic le Scroll va s'arrêter.
Je vais faire des tests pour utiliser le même principe que pour la ListBox (zone couverte ou pas par la souris).

Sinon, voilà ce que j'ai fait
  1. La fonction HookMouse contient des tas de trucs parfaitement inutiles.
    J'ai fait un nettoyage de simplification des tous ces Handles qui ne servent à rien.
    Ça ce n'est pas un vrai problème pour toi, tu peux laisser les choses en l'état.

  2. Le Scroll dans une ListBox ou une ComboBox ne fonctionne correctement (pas de blocages, hésitations) que si son UserForm est actif (en ForeGround).
    Or on peut très passer de la feuille au UserForm ou d'un 1er UserForm à un 2ème UserForm sans qu'il devienne actif. Donc il faut en sécuriser l'activation (SetForeGroundWindow).
 

patricktoulon

XLDnaute Barbatruc
ok j'attends de voir
oui en sélectionnant une cellule dans l feuille après le scroll s'arrête dans le mien aussi
mais j'espérais avoir le même résultat que pour les listboxs c'est à dire sans aucune autre action que déplacer la souris
pour les combobox visiblement c'est plus compliqué
pour le userform je n'ai pas de soucis ça va

pour les feuilles j'utilise getcursorpos et le typename retourné par rangefrompoint
pour les userform les rectangles des controls sont bien identifié au millimètre près
et absolument tout se fait dans la levelproc(en addressof)
c'est ça qui a de bien car des qu'elle démarre tant que c'est pas arrêté le control est constant

pas facile de mélanger les deux (controls dans feuille/control dans userforms)
en feuille getwindowrect bye!bye! ça marche pas très bien
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
pour les combobox visiblement c'est plus compliqué
Je dirais même que c'est insoluble car on ne peut pas savoir (sauf à gérer un flag applicatif non envisageable pour le Scroll) si la ComboBox est déployée ou non. Donc on ne connait pas sa zone d'affichage.
Sauf à trouver au niveau APi si il y a quelque chose pour atteindre cette DropDown zone.

C'est pour ça que pour le ComboBox je suis parti sur l'évènement ComboBox_Click() qui finit TOUJOURS par se déclencher ON / OFF, avec ce petit inconvénient que le Scroll ComboBox continue tant qu'il n'y a pas de clic n'importe ou (dans la feuille, dans un UserForm, dans une autre application).

Maintenant on peut limiter les dégâts car si on ne sait pas où elle finit en bas, on sait où sont ses limites haute et latérales et on peut alors tester la position de la souris. Mais ça ne couvre que 75% des cas.
 

patricktoulon

XLDnaute Barbatruc
ha !!! oui c'est assez simple en fait
dim fentreenfantdecombo 'handle de la fenetre enfant dépliée
fentreenfantdecombo=api getwindow( hwndcombo,5)'l'enfant de la combo
avec l'apiwindowfrompoint on voit si le handle donné est le même que fentreenfantdecombo

grosomodo c'est ça

à tester avec getcursopos pour éviter toute cette usine a gaz bien sur ;)
 

patricktoulon

XLDnaute Barbatruc
bon ben voila j'ai le handle du dépliant de la combo
faut savoir qu'il change a chaque fois que l'on déroule et c'est normal c'est une nouvelle child a chaque fois
c'est donc bien dans la levelproc qui faudra le faire
quand je déroule j'ai le handle child quand j' enroule (dropUp) c'est le handle de la combo qui m'est donné
terminé j'ai mon moteur
démonstration
demo.gif

youhou!! j'ai encore trouver un truc
et beaucoup moins compliqué que ton lien

en comparant le textbox 2 et 3 on variabilise ces deux donnée a la place des deux textbox
et le tour est joué
demo.gif
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Purée, c'est pas simple l'affaire.
J'ai abandonné le GetFocus() qui ne marche pas toujours quand on vient d'une autre fenêtre au profit du WindowFromPoint() qui donne le Hanlde du Control de UserForm.

J'ai gardé mon système basé sur des Click pour les ComboBox qui marche aussi pour les ActiveX, toujours avec cette particularité de la conservation du Scroll des ComboBox jusqu'au 1er clic, qui n'est guère gênant en réalité. Je verrai comment tu fais pour récupérer les Handles des ComboBox et j'adapterai éventuellement.

Il faut essayer avec plein de configurations, c'est pourquoi mon fichier de test joint comporte:
- des ActiveX ListBox et ComboBox (j'ai choisi de les traiter mais on pourrait s'en passer)
- des UserForms séparés ListBox et ComboBox
- un UserForm commun ListBox et ComboBox
Ce sont les passages directs de l'un à l'autre qu'il faut tester, notamment avec une ComboBox déployée.
 

Pièces jointes

  • VBA Scroll Souris en ListBox et ComboBox.xlsm
    70.3 KB · Affichages: 10

Usine à gaz

XLDnaute Barbatruc
Purée, c'est pas simple l'affaire.
J'ai abandonné le GetFocus() qui ne marche pas toujours quand on vient d'une autre fenêtre au profit du WindowFromPoint() qui donne le Hanlde du Control de UserForm.

J'ai gardé mon système basé sur des Click pour les ComboBox qui marche aussi pour les ActiveX, toujours avec cette particularité de la conservation du Scroll des ComboBox jusqu'au 1er clic, qui n'est guère gênant en réalité. Je verrai comment tu fais pour récupérer les Handles des ComboBox et j'adapterai éventuellement.

Il faut essayer avec plein de configurations, c'est pourquoi mon fichier de test joint comporte:
- des ActiveX ListBox et ComboBox (j'ai choisi de les traiter mais on pourrait s'en passer)
- des UserForms séparés ListBox et ComboBox
- un UserForm commun ListBox et ComboBox
Ce sont les passages directs de l'un à l'autre qu'il faut tester, notamment avec une ComboBox déployée.
Bonjour,
Testé également chez moi Office365 = Pas de souci :)
 

patricktoulon

XLDnaute Barbatruc
J'ai gardé mon système basé sur des Click pour les ComboBox qui marche aussi pour les ActiveX, toujours avec cette particularité de la conservation du Scroll des ComboBox jusqu'au 1er clic, qui n'est guère gênant en réalité. Je verrai comment tu fais pour récupérer les Handles des ComboBox et j'adapterai éventuellement.
oui je n'est aucun doute sur le fait que ça fonctionne je vais tester quand même

un problème IMPORTANT!!:
c'est le fait qu'il faut cliquer(donc sélectionner un item) pour démarrer le scroll molette
si les event click ou change contiennent des actions a faire après clic comme c'est a 99% le cas
ça va pas coller

j'ai mis au point un petit module de rien du tout pour te faire la démonstration avec un userform et une combobox
ce module hyper simple a deux fonctions (celles qui nous intéressent)
j'ai garder le get focus car je n'utilise pas le set focus puisque c'est déclenché dans le mouseup
il ne peut y avoir d’ambiguïté(si la fonction est appelée c'est que la combo a le focus )

le module de test version beta
VB:
'**********************************************************************************
' __        _____  ___   .  ___         _____  ___             ___
'|__|  /\     |   |   |  | |     | /      |   |   | |   | |   |   | |\  |
'|    /__\    |   |---   | |     |/\      |   |   | |   | |   |   | | \ |
'|   /    \   |   |   \  | |___  |  \     |   |___| |___| |__ |___| |  \|

'***********************************************************************************
'module de fonction pour combobox
'1 fonction << GetComboboxDropdownState >> renvoie le status d'un combobox (developpée ou pas )
'2 fonction << GetComboboxChildRectangle >> renvoie une variable rect (le rectangle en pixel de la fenetre child de la combobox )
'version: beta
'date version:28/10/2022
'Auteur:Patricktoulon
'un userform de test l'accompagne
'les fonction sont appelée dans le le mouseup du control
'ce qui implique que le dropdown_click appelle aussi
'par contre le click dans la fentre child non
'j'ai fait comme ça pour limiter l'appel seulement quand la combobox n'est pas développée
'seul le click sur le dropdownbutton agit et appelle les fonctions (MEME SI LES APPELS SONT DANS LE MOUSEUP!!!)
'**********************************************************************************
#If VBA7 Then
    Private Declare PtrSafe Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As LongPtr
    Private Declare PtrSafe Function GetFocus Lib "user32" () As LongPtr
    Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long
#Else
    Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
    Private Declare Function GetFocus Lib "user32" () As Long
    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
#End If

Private Type POINTAPI: X As Long: Y As Long: End Type
Type RECT: Left As Long: Top As Long: Right As Long: Bottom As Long: End Type

'Donne le status de la combobox( developpée ou pas)--->boolean
Function GetComboboxDropdownState(ByVal combo As msforms.ComboBox) As Boolean
    Dim r As RECT: r = GetComboboxChildRectangle(combo)
    GetComboboxDropdownState = r.Left > 0
End Function

'fonction qui renvoie une variable de type rect  ce rect contient les points de la fenetre child de la combobox
Function GetComboboxChildRectangle(ByVal combo As msforms.ComboBox) As RECT
    Dim pos As POINTAPI, rct As RECT, H1&, H2&, ppx#
    ppx = CreateObject("WScript.Shell").RegRead("HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\AppliedDPI") / 72
    H1 = GetFocus
    GetCursorPos pos
    H2 = WindowFromPoint(pos.X, pos.Y + combo.Height * ppx)
    If H1 <> H2 Then GetWindowRect H2, rct
    'a fin d'inclure la partie rectangle du combobox lui meme dans le rectangle  on l'enleve du rct.top
    rct.Top = rct.Top - (combo.Height * ppx)
    If rct.Left = 0 Then rct.Top = 0
    GetComboboxChildRectangle = rct    ' H1 <> H2
End Function

comment elle est appelée dans le userform
VB:
Option Explicit
Private Sub ComboBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'si on veut juste le rectangle de la fenêtre enfant de la combobox
    
    Dim r As RECT
    r = GetComboboxChildRectangle(ComboBox1)
    temoin = "rect.left :" & r.Left & vbCrLf & "rect.top :" & r.Top & vbCrLf & "rect.right:" & r.Right & vbCrLf & "rect.bottom : " & r.Bottom

'si on veut juste  le DropDownState
    
    'temoin = "DropDownState : " & GetComboboxDropdownState(ComboBox1)

End Sub

le fichier en démo joint
maintenant je vais tester ton fichier
 

Pièces jointes

  • combobox dropdown or not dropdown handle child return .xlsm
    26.8 KB · Affichages: 7

Membres actuellement en ligne

Statistiques des forums

Discussions
314 655
Messages
2 111 604
Membres
111 217
dernier inscrit
aladinkabeya2