Affichage TreeView ?

Résolu
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005 - 16 oct. 2004 à 13:20
skowee59 Messages postés 78 Date d'inscription vendredi 17 janvier 2003 Statut Membre Dernière intervention 29 juin 2006 - 10 mai 2005 à 11:26
Je cherche à appliquer un "Scroll" calculé aux barres de défilement horizontales et verticales afin de positionner le "node" sélectionné en haut et à gauche du trv !? J'ai essayé différentes approches et c'est la m...

Quelqu'un aurait une idée ?

21 réponses

chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
22 oct. 2004 à 06:03
:) Bon ben cette fois on y est, j'ai viré le GetScrollInfo, mais je conserve les deux fonctions séparées car je ne fait pas les deux dans tous les cas. J'ai viré aussi le Select dans RecalculerScrollBars (ci-dessous) et tout marche en tenant compte de la taille des icônes de l'imagelist liée au treeview.

Comme j'ai bien compris je vais maintenant "accepter" la réponse pour que les suivants pointent directement sur LA BONNE REPONSE.

A Bientôt.
Christophe.

Private Sub RecalculerScrollBars(iTab As Integer)
'Calcul du décalage à droite selon le niveau courant de la hiérarchie et la taille de l'icône.
With m_tagSCROLLINFO
.cbSize = LenB(m_tagSCROLLINFO)
.fMask = SIF_ALL .nPos iNivTrvSel(iTab) * TAILLE_ICONE + IIf(iNivTrvSel(iTab) NIV_SEC, 0, 2)
End With
SetScrollInfo trvContacts(iTab).hwnd, SB_HORZ, m_tagSCROLLINFO, True
End Sub

PS : J'ai posé une autre question sur les TreeView et ListView dans le forum mais j'ai eu moins de chance jusque là (pas de réponse).

PS 2 : Dès que j'aurai bouclé mon projet je ferais un super control TreeView et je poserais les sources...
3
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
22 oct. 2004 à 14:20
si ça peut t'aider.
donne le niveau du node sélectionné:

Public Function GetLevel() As Long
  Dim nod1           As Node
  Dim nLevel         As Integer

  Set nod1 = Tv.SelectedItem

  Do While (nod1 Is Nothing) = False
    nLevel = nLevel + 1
    Set nod1 = nod1.Parent
  Loop

  GetLevel = nLevel
    
End Function
3
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
16 oct. 2004 à 19:24
pour le Scroll Vertical:
il faut utiliser EnsureVisible pour le premier à afficher en haut et pour le dernier à afficher en bas.
pour le premier c'est facile:
Treeview.SelectedItem.EnsureVisible
pour le dernier c'est une autre histoire !
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
17 oct. 2004 à 13:49
J'ai déjà essayé le EnsureVisible, ça ne produit pas l'effet que je souhaite :
- effectuer un scroll vertical et horizontal pour que l'icône du node sélectionné apparaisse en haut et à gauche ("top 0", "left0") du treeview.

Merci quand même pour la réponse.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
17 oct. 2004 à 19:37
J'ai trouvé quelques trucs pour agir sur les Scrollbars:

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Const WM_HSCROLL = &H114
Private Const WM_VSCROLL = &H115

Private Const SB_LINEUP = 0
Private Const SB_LINEDOWN = 1
Private Const SB_PAGEUP = 2
Private Const SB_PAGEDOWN = 3
Private Const SB_THUMBPOSITION = 4
Private Const SB_THUMBTRACK = 5
Private Const SB_TOP = 6
Private Const SB_BOTTOM = 7
Private Const SB_ENDSCROLL = 8

Private Const SB_LINELEFT = 0
Private Const SB_LINERIGHT = 1
Private Const SB_PAGELEFT = 2
Private Const SB_PAGERIGHT = 3
Private Const SB_LEFT = 6
Private Const SB_RIGHT = 7

'Scrollbar verticale en haut
SendMessage Treeview.hwnd, WM_VSCROLL, SB_TOP, 0

'Scrollbar verticale en bas
SendMessage Treeview.hwnd, WM_VSCROLL, SB_BOTTOM, 0

'Scrollbar verticale une ligne en haut
SendMessage Treeview.hwnd, WM_VSCROLL, SB_LINEUP, 0

'Scrollbar verticale une ligne en bas
SendMessage Treeview.hwnd, WM_VSCROLL, SB_LINEDOWN, 0

'Scrollbar horizontale à gauche
SendMessage Treeview.hwnd, WM_VSCROLL, SB_LEFT, 0

'Scrollbar horizontale à droite (ne marche pas ?)
SendMessage Treeview.hwnd, WM_VSCROLL, SB_RIGHT, 0

pour revenir à ton problème, une solution qui marche que si le node sélectionné n'est pas trop bas:
Dim x As Integer
SendMessage Treeviex.hwnd, WM_VSCROLL, SB_BOTTOM, 0
x = Treeview.SelectedItem.Index
Treeview.Nodes(x).Selected = True
SendMessage Tv.hwnd, WM_HSCROLL, SB_LEFT, 0
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
20 oct. 2004 à 08:58
Je vais tester ça très vite, ça me semble être la bonne approche, je te remercie donc par avance...
0
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
20 oct. 2004 à 10:32
Renseignements divers sur les Scrollbars:

Déclarations

Private Enum HORZ_VERT
    SB_HORZ =  0&
    SB_VERT = 1&
End Enum

Public Enum SIF_MASK
    SIF_RANGE = &H1&
    SIF_PAGE = &H2&
    SIF_POS = &H4&
    SIF_DISABLENOSCROLL = &H8&
    SIF_TRACKPOS = &H10&
    SIF_ALL = SIF_RANGE Or SIF_PAGE Or SIF_POS
End Enum

Private Type SCROLLINFO
    cbSize As Long
    fMask As SIF_MASK
    nMin As Long
    nMax As Long
    nPage As Long
    nPos As Long
    nTrackPos As Long
End Type

Private Declare Function GetScrollInfo Lib "user32" _
       (ByVal hwnd As Long, ByVal fnBar As HORZ_VERT, lpScrollInfo As _
        SCROLLINFO) As Long
                
Private Declare Function SetScrollInfo Lib "user32" _
       (ByVal hwnd As Long, ByVal fnBar As HORZ_VERT, lpcScrollInfo As _
        SCROLLINFO, ByVal fRedraw As Boolean) As Long


Utilisation

    Dim m_tagSCROLLINFO As SCROLLINFO
    
    m_tagSCROLLINFO.cbSize  = LenB(m_tagSCROLLINFO)
    m_tagSCROLLINFO.fMask = SIF_ALL
    Call GetScrollInfo(Tv.hwnd, SB_VERT, m_tagSCROLLINFO)


Résultats

nMax donne le nombre maximum de Lignes à afficher
nPos  donne la position de la Scrollbar
nPage donne le nombre de Ligne du Treeview

La position mini de la Scrollbar est zéro
La position maxi de la Scrollbar est nMax - nPage +1


Conclusions

On peut agir sur les deux Scrollbars avec SB_HORZ ou SB_VERT
avec GetScrollInfo on obtient les renseignements
avec SetScrollInfo on doit pouvoir les modifier
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
20 oct. 2004 à 12:31
Après avoir testé, je continue à croire que c'est la bonne méthode, cependant, avec le code suivant (s'exécutant sur le Mouse_Down du TreeView) :

With .SelectedItem
If .Children Then
.Expanded = Not (.Expanded)
'On initialise la ScrollBar Horizontale A GAUCHE
SendMessage trvContacts(Index).hwnd, WM_HSCROLL, SB_LEFT, 0 '2
If .Expanded Then

'On initialise la ScrollBar Verticale EN BAS...
SendMessage trvContacts(Index).hwnd, WM_VSCROLL, SB_BOTTOM, 0 '1

'On se décale A DROITE d'une page ?!
SendMessage trvContacts(Index).hwnd, WM_HSCROLL, SB_PAGERIGHT, 0 '3

'On demande ensuite au trv de nous rendre visible,
'je crois que c'est ça qui fait que mon icône à gauche du
'texte disparait ?!
.EnsureVisible
End If
End If
End With

J'obtiens quasiment le résultat souhaité "sauf que" mon icône n'est plus affiché. Je pense qu'il faudrait pouvoir calculer la largeur du SelectedItem (selon son contenu, sa police, etc., pas de problème) et calculer la marge possible de défilement horizontal, pour calculer le décalage à effectuer, et donc effectuer le .ensurevisible avant le décalage à droite ainsi calculé !?!

Si tu as une idée sur comment calculer ce pu.... de décalage à droite je suis preneur ?

Encore une fois merci pour m'avoir mis sur la bonne piste, après j'en vois plus qu'une réécrire un control TreeView !

PS : Dans ta précédente réponse je crois que ton Scroll Horizontal ne marche pas car tu envoies WM_VSCROLL au lieu de WM_HSCROLL.
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
20 oct. 2004 à 12:34
Sorry je viens juste de voir la suite de ta réponse, je regarde...
Je crois que tu l'as envoyé pendant que j'écrivais la mienne !
0
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
20 oct. 2004 à 12:47
pour calculer la Longueur d'un texte en pixels:

Dim m As Long
m = Treeview.Parent.TextWidth("Texte à tester")
'm doit être en pixels
m = m / Screen.TwipsPerPixelX
'ajouter la largeur de la Scrollbar
m=m + GetSystemMetrics(SM_CXVSCROLL) '17 pixels

nb: problème de police entre le Treeview et Treeview.Parent (doivent être les mêmes)
0
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
20 oct. 2004 à 12:59
Fonction Complète:

Private Const WM_HSCROLL = &H114
Private Const WM_VSCROLL = &H115

Private Const SB_LEFT = 6
Private Const SB_RIGHT = 7

Private Const TV_FIRST            As Long = &H1100
Private Const TVM_DELETEITEM      As Long = (TV_FIRST + 1)
Private Const TVM_GETITEMRECT     As Long = (TV_FIRST + 4)
Private Const TVM_GETNEXTITEM     As Long = (TV_FIRST + 10)
Private Const TVM_SELECTITEM      As Long = (TV_FIRST + 11)
Private Const TVM_GETITEM         As Long = (TV_FIRST + 12)
Private Const TVM_SETITEM         As Long = (TV_FIRST + 13)
Private Const TVM_GETEDITCONTROL  As Long = (TV_FIRST + 15)
Private Const TVM_HITTEST         As Long = (TV_FIRST + 17)     '@@ v02.02.00

Private Enum TVGN_Flags
    TVGN_ROOT = &H0
    TVGN_NEXT = &H1
    TVGN_PREVIOUS = &H2
    TVGN_PARENT = &H3
    TVGN_CHILD = &H4
    TVGN_FIRSTVISIBLE = &H5
    TVGN_NEXTVISIBLE = &H6
    TVGN_PREVIOUSVISIBLE = &H7
    TVGN_DROPHILITE = &H8
    TVGN_CARET = &H9
    TVGN_LASTVISIBLE = &HA
End Enum

Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" _
       (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Declare Function SendMessageAny Lib "user32" Alias "SendMessageA" _
       (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

Private Sub SetFirstVisibleNode(ByVal Node As MSComctlLib.Node)
    '
    '## Set the first visible Node of a TreeView control
    '
    Dim hItem   As Long
    Dim selNode As MSComctlLib.Node

    LockWindowUpdate Treeview.hwnd
    With Treeview
        '## Remember the node currently selected
        Set selNode = .SelectedItem
        '## Make the Node the select Node in the control
        Set .SelectedItem = Node
        '## Now we can get its handle
        hItem = SendMessageAny(.hwnd, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0&)
        '## Restore node that was selected
        Set .SelectedItem = selNode
        '## Make it the fist visible Node
        SendMessageLong .hwnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, hItem
        SendMessageLong .hwnd, WM_HSCROLL, SB_LEFT, 0
        End With
    LockWindowUpdate 0

End Sub


pour utiliser:
SetFirstVisibleNode Treeview.SelectedItem
Treeview.SetFocus
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
21 oct. 2004 à 10:22
Après test cette méthode me semble encore mieux, voici le seul code qui me reste après adaptation à mon cas :

Public Sub SelectedFirstVisible(trv As TreeView)
'## Make the .SelectedItem of a TreeView control the first visible
Dim hItem As Long
With trv
If Not (.SelectedItem Is Nothing) Then
LockWindowUpdate .hwnd
'## Now we can get its handle
hItem = SendMessageAny(.hwnd, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0&)
'## Make it the fist visible Node
SendMessageLong .hwnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, hItem
SendMessageLong .hwnd, WM_HSCROLL, SB_LEFT, 0
End If
End With
LockWindowUpdate 0
End Sub

Le fonctionnement est parfait pour le positionnement vertical, mais j'utilise encore GetScrollInfo et SetScrollInfo pour faire le décalage horizontal (ça marche bien, voir code ci-dessous RecalculerScrollBars) mais je me dis qu'il doit suffir d'une petite ligne de plus dans SelectedFirstVisible (ci-dessus) pour effectuer le décalage horizontal?

Me trompe-je ?

Encore merci !

PS : C'est la première fois que je pose une question sur le forum, j'ai vu qu'il y avait un système de notation des réponses recues, je ne me pose pas la question de la note à donner à la qualité de tes réponses (note maximum), mais peut-on mettre plusieurs notes quand une discussion comporte plusieurs réponses ?

Private Sub RecalculerScrollBars(iTab As Integer)
Dim iLeft As Integer
'Calcul du décalage à droite selon le niveau courant de la hiérarchie
Select Case iNivTrvSel(iTab)
Case NIV_SEC
iLeft = 0
Case NIV_REG
iLeft = 34
Case NIV_DEP
iLeft = 68
Case NIV_FIC
iLeft = 102
End Select
GetScrollInfo trvContacts(iTab).hwnd, SB_HORZ, m_tagSCROLLINFO
With m_tagSCROLLINFO
.cbSize = LenB(m_tagSCROLLINFO)
.fMask = SIF_ALL
.nPos = iLeft
End With
SetScrollInfo trvContacts(iTab).hwnd, SB_HORZ, m_tagSCROLLINFO, True
End Sub
0
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
21 oct. 2004 à 12:41
Salut.

Je suis content que le code marche, je ne pense pas qu'il y ait d'autres méthodes plus simples pour déplacer la Scrollbar Horizontale, je ne conaissais pas NIV_SEC, NIV_REG, etc..., je vais étudier la question.

Pour les réponses reçues, c'est pas un système de notation, c'est seulement une façon d'indiquer que la réponse à été trouvée. Tu peux cocher plusieurs cases en même temps.

Daniel
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
21 oct. 2004 à 15:33
Salut,

les constantes NIV_... sont à moi (je les gère selon l'état du treeview).

Ma dernière question était de savoir si je pouvais me passer des APIs GetScrollInfo et SetScrollInfo en modifiant légérement la super fonction ci-dessous (qui pour le moment fait très bien le décalage vertical) pour qu'elle puisse appliquer mon décalage horizontal ?

A bientôt.

Public Sub SelectedFirstVisible(trv As TreeView)
'## Make the .SelectedItem of a TreeView control the first visible
Dim hItem As Long
With trv
If Not (.SelectedItem Is Nothing) Then
LockWindowUpdate .hwnd
'## Now we can get its handle
hItem = SendMessageAny(.hwnd, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0&)
'## Make it the fist visible Node
SendMessageLong .hwnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, hItem
SendMessageLong .hwnd, WM_HSCROLL, SB_LEFT, 0
End If
End With
LockWindowUpdate 0
End Sub
0
Gobillot Messages postés 3140 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 11 mars 2019 34
21 oct. 2004 à 18:06
pas moyen d'éviter SetScrollBar par contre on peut se passer de GetScrollBar
faire une seule procédure avec les deux:

Public Sub SelectedFirstVisible(trv As TreeView)
 '## Make the .SelectedItem of a TreeView control the first visible
    Dim hItem As Long
    Dim m_tagSCROLLINFO As SCROLLINFO
    Dim iLeft As Integer
    
With trv
If Not (.SelectedItem Is Nothing) Then
LockWindowUpdate .hwnd
'## Now we can get its handle
hItem = SendMessageAny(.hwnd, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0&)
'## Make it the fist visible Node
SendMessageLong .hwnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, hItem

'   Calcul du décalage à droite selon le niveau courant de la hiérarchie
   Select Case .SelectedItem.Text
      Case NIV_SEC: iLeft = 0
      Case NIV_REG: iLeft = 34
      Case NIV_DEP: iLeft = 68
      Case NIV_FIC: iLeft = 102
      End Select
      
         m_tagSCROLLINFO.cbSize = LenB(m_tagSCROLLINFO)
         m_tagSCROLLINFO.fMask = SIF_POS
         m_tagSCROLLINFO.nPos = iLeft
         SetScrollInfo .hwnd, SB_HORZ, m_tagSCROLLINFO, True

         LockWindowUpdate 0
         End If
      End With
End Sub


suggestion:
pour se passer de Select Case dans la procédure, inclure la valeur dans le tag à la création, et la reprendre par:
m_tagSCROLLINFO.nPos = .SelectedItem.Tag
problèmes:
les valeurs calculées: 0,34,68,102 sont des valeurs relatives par rapport au maxi, et celui-ci peut changer en fonction des noeuds visibles ou non, et aussi si le resize est gérer.
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
23 oct. 2004 à 09:58
Je mets ça de côté pour plus tard, je m'attaque maintenant à un autre sujet passionnant (dernier gros bug) de mon produit : les ListViews... Peut-être puis-je te soumettre mon problème ? Parce que les autres ils répondent pas trop à mes questions ! Faut dire que j'ai honte de la dernière question que j'ai envoyé (peut-on les supprimer vite fait les questions débiles ?) J'ai demandé comment on change la hauteur de police des TreeViews et ListViews parce que j'avais pas trouvé la propriété .FontSize et qu'il fallait utiliser .Font.Size !!!
Bon je m'y remets, pour voir déjà comment poser une question claire et précise sur mon vrai problème de ListView, il y aura bientôt une version de démo téléchargeable sur mon "site" (état embryonaire, il ya quand même la version précédente de mon logiciel à moi que je fait depuis 5 ans.)

A + et encore merci.

Christophe.
0
skowee59 Messages postés 78 Date d'inscription vendredi 17 janvier 2003 Statut Membre Dernière intervention 29 juin 2006
9 mai 2005 à 11:25
Bonjour,

Moi mon petit souci c'est que lorsque j'utilise un TreeView, la
scrollbar vertical apparait dès le départ (même si il n'y a aucun
noeud). De plus, le style est celui de Windows "classique". Alors que
la scrollbar horizontal apparait quand il faut et avec le style XP.

Je pense qu'il s'agit d'un bug aléatoire mais si quelqu'un a une solution pour forcer la disparition de la scrollbar vertical...

Zerocool59
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
10 mai 2005 à 08:52
Bonjour,

Pour ma part j'ai réglé ce problème en me faisant un ocx qui peut contenir n'importe quel autre contrôle et qui gère les scrollbars comme je le souhaite. Je n'utilise donc plus les scrollbars automatiques des contrôles. Il y a sûrement des APIs qui permettent de faire disparaitre une scrollbar... Si la solution à base d'ocx te convient fais-moi le savoir je t'enverrai le source du contrôle.

Bon courage.

chrisrol
0
skowee59 Messages postés 78 Date d'inscription vendredi 17 janvier 2003 Statut Membre Dernière intervention 29 juin 2006
10 mai 2005 à 09:06
Je suis preneur ;-)
Merci pour ton aide.

Zerocool59
0
chrisrol Messages postés 14 Date d'inscription vendredi 15 octobre 2004 Statut Membre Dernière intervention 9 mai 2005
10 mai 2005 à 11:21
Je viens d'essayer de déposer mon source mais il semblerait que le fichier zip soit tros gros (513 Ko) ! J'ai demandé au admin quelle était la limite de taille, j'attends leur réponse. Si tu souhaites que je te l'envoie donne moi ton adresse mail, la mienne est [mailto:chrisrol@free.fr chrisrol@free.fr].

@+

chrisrol
0
Rejoignez-nous