XL 2016 Quelle API pour savoir si une ListBox (UserForm ou ActiveX) a sa ScrollBar Verticale présente ?

Dudu2

XLDnaute Barbatruc
Bonjour les XLDNautes,

Si on peut, sans API, savoir si une ComboBox a son ascenseur affiché grâce à la différence (ComboBox.ListCount - ComboBox.ListRows) ce n'est pas possible avec les ListBoxes.
Certes on connaît son ListBox.TopIndex mais il n'existe pas de ListBox.BottomIndex.
Un approximation est possible avec la ListBox.Font.Size mais ça reste imprécis.

Reste l'API qui pourrait indiquer la présence d'une Vertical ScrollBar mais mes essais sont restés infructueux.
Merci pour toute suggestion.
 
Solution
pour ce qui est de cette discussion j'ai revue la chose pour les ListBox dans userform et feuille

Dranreb

XLDnaute Barbatruc
Effectivement vous pouvez mettre sa propriété Autosize à True avant d'affecter sa List, et après tester si sa Height est supérieure à celle ou vous voudrez la ramener après l'avoir remise à False.
Ben non, à ma grande surprise, une ListBox n'a pas de propriété Autosize. Elle a une propriété IntegralHeight qui n'est apparemment là que pour décorer.
Alors le plus simple c'est de déterminer expérimentalement à partir de quel nombre de lignes la barre est affichée.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
tiens je l'ai retrouvée dans mon cafoutche
ok j'explique
le principe est d'ajouter dynamico un label et lui donner les meme properties que la listbox font size font name bold etc.. etc...
et de le mettre en autosize(pareil que pour autofit pour les cellules)
ben après c'est simple
si le heightlabel * le listcount <= que le height de la listbox alors non sinon oui

exemple

VB:
'function coded!by patricktoulon
'date 2022  for XLD
'know if the listbox has the vertical scrollbar

Option Explicit
Private Sub CommandButton1_Click()
Dim I&
ListBox1.Clear
For I = 1 To 10
ListBox1.AddItem Round((Rnd * 1000))
Next
End Sub

Private Sub CommandButton2_Click()
Dim I&
ListBox1.Clear
For I = 1 To 11
ListBox1.AddItem Round((Rnd * 1000))
Next
End Sub

Private Sub CommandButton3_Click()
MsgBox " a la scrollverticale : " & HasVerticalScrollBar(ListBox1)
End Sub

Function HasVerticalScrollBar(Ctrl As MSForms.Control)
Dim lab
Set lab = Me.Controls.Add("forms.Label.1", "X3Xy")
With lab
.Height = 2: .Caption = "A": .Font.Size = Ctrl.Font.Size: .Font.Name = Ctrl.Font.Name
.Font.Bold = Ctrl.Font.Bold: .BorderStyle = Ctrl.BorderStyle: .AutoSize = True
HasVerticalScrollBar = (.Height * Ctrl.ListCount) > Ctrl.Height
Me.Controls.Remove "X3Xy"
End With
End Function
demo.gif

je te donne le fichier exemple
 

Pièces jointes

  • savoir si la listbox a la scrollbar enclenchée ou pas .xlsm
    15.2 KB · Affichages: 2

Dudu2

XLDnaute Barbatruc
Dommage que cette API qui fonctionne parfaitement pour trouver les Handles des Controls ActiveX activés ne fonctionne que partiellement (ListBoxes) ou pas du tout (ComboBoxes) pour les Handles des fenêtres des Controls de UserForm.
 

Pièces jointes

  • Classeur1.xlsm
    41 KB · Affichages: 1

patricktoulon

XLDnaute Barbatruc
re
les listbox ou Frames , tu n'a besoins d'aucune api ni de lui donner le focus ,tu a besoins seulement l’abréviation de uiautomationclient qui est incorporée au controls

msgbox userformX.listbox1.[_gethWnd]

elle n'est malheureusement pas implémenté pour les combo qui sont des suites de fenêtres
il faut tout coder la procédure uiautomationclient qui peut être verbeuse en effet mais très efficace
j'essaie de retrouver mes run de puis tout a l'heure je suis certains d'avoir eu besoins de ça un jour

contrairement au api win
avec UIAutomationclient tu peux trouver les child les scroll et autre boutons eventuel sur la plaque du controls et autre fonction comme le rectangle par exemple
 

Dudu2

XLDnaute Barbatruc
Bonjour,
La ComboBox de UserForm c'est râpé en effet, elle est impossible à trouver quelque soit la méthode.
J'ai essayé 3 méthodes pur trouver le Handle du Control
  1. WindowFromPoint
    -> pas bon

  2. EnumChildWindows
    -> ok mais on ne peut que difficilement reconnaître la fenêtre qu'on cherche lorsqu'on parcours les Child Windows.
    Je ne sais pas retrouver le nom d'un Control à partir du Handle de sa fenêtre. Le GetWindowText ne donne rien.
    La seule chose que j'ai pu faire c'est comparer la position du RECT ce qui est assez simple pour un Control ActiveX mais plus aléatorire avec un Control de UserForm.

  3. GetFocus
    -> ok, c'est la seule méthode qui couvre tous les cas (sauf ComboBox UserForm évidemment) mais il faut:
    - Activer les Controls ActiveX préalablement
    - SetFocus sur les Controls UserForm ce qui oblige à une manip spéciale s'il n'y a qu'un seul Control "focusable" dans le UserForm. En plus l'action proactive du SetFocus peut perturber la logique d'un traitement utilisateur.
    VB:
    '--------------------------
    'Fonctionne pour les Controls ActiveX. Un Control.Activate sera effectué.
    'Fonctionne pour les Controls UserForm ListBox pour lesquels un SetFocus sera effectué.
    'NE fonctionne PAS Controls UserForm ComboBox.
    '--------------------------
    Public Function GetControlHandleByGetFocus(Ctl As Object) As LongPtr
        Dim UserFormControl As MSForms.Control
        Dim NbUserFormFocusControls As Integer
        Dim TxB As MSForms.TextBox
    
        'Parent is Worksheet
        If TypeOf Ctl.Parent Is Worksheet Then
            Ctl.Activate
            GetControlHandleByGetFocus = GetFocus
    
        'Parent is UserForm
        Else
            'Does NOT work for ComboBoxes
            'If TypeOf Ctl Is MSForms.ComboBox Then Exit Function
     
            'Count the number of Controls in the UserForm that can be SetFocus
            On Error Resume Next
            For Each UserFormControl In Ctl.Parent.Controls
                UserFormControl.SetFocus
                If Err.Number = 0 Then
                    NbUserFormFocusControls = NbUserFormFocusControls + 1
                    If NbUserFormFocusControls >= 2 Then Exit For
                Else
                    Err.Clear
                End If
            Next UserFormControl
            On Error GoTo 0
     
            'Not 2 "focusable" Controls in the UserForm
            If NbUserFormFocusControls < 2 Then
                Set TxB = Ctl.Parent.Controls.Add("forms.TextBox.1", Name:="TextBoxForFocus")
            End If
     
            'Works ONLY if at least another "focusable" Control in the UserForm
            Ctl.Enabled = False
            Ctl.Enabled = True
     
            'Not 2 "focusable" Controls in the UserForm
            If NbUserFormFocusControls < 2 Then
                Ctl.Parent.Controls.Remove "TextBoxForFocus"
            End If
    
            'Works ONLY if the Control did not have prior focus (reason why Ctl.Enabled = False / True)
            Ctl.SetFocus
            GetControlHandleByGetFocus = GetFocus
        End If
    End Function
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Tu as utilisé la fonction ci-dessus ?
Si tu fais un SetFocus qui n'est pas "nouveau" (le Focus était sur un autre Control), alors c'est effectivement le UserForm qu'on récupère. Il faut vraiment forcer un "nouveau" SetFocus.

Essaie avec ce fichier.
 

Pièces jointes

  • GetControlHandleMethods.xlsm
    60.9 KB · Affichages: 2

Statistiques des forums

Discussions
312 216
Messages
2 086 344
Membres
103 194
dernier inscrit
rtison