Forcer les cochage des pères dans une Treeview quand les fils sont cohés
supertoms
Messages postés32Date d'inscriptionjeudi 10 mai 2007StatutMembreDernière intervention27 janvier 2013
-
15 avril 2008 à 09:23
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 2021
-
17 avril 2008 à 05:51
Salut à tous,
je cherche 2 fonctions pour ma treeview avec checkbox, avec une urgence pour la première :
1) J'aimerai que quand un noeud fils est coché dans le treeview, ses pères soient eux-aussi obligatoirement cochés.
2) Je voudrai aussi que quand la totalité des fils d'un treeview ne sont pas cochés, la checkbox du père est "coché grisée". Et quand la totalité des fils sont cochés, la checkbox du père est "cohée blanche".
Autant on trouve facilement des fonctions pour cocher automatiquement les enfants, autant je n'arrive vraiment pas a trouver de fonction pour forcer le cochage des noeuds parents quand un ou plusieurs des enfants sont cochées, pouvez-vous maider ?
jrivet
Messages postés7392Date d'inscriptionmercredi 23 avril 2003StatutMembreDernière intervention 6 avril 201260 15 avril 2008 à 14:29
Re,
>[auteur/SUPERTOMS/1058141.aspx supertoms] (le prends pas mal): On va pas te mâcher tout le travail, commence par assimiler ce que tu viens de voir. et ensuite tu chercheras ce que veux dire sous-Classer. et là tu reviendras.
Le forum ne se résume pas à : "Ca donne quoi en code stp?"
l'idée serait de jouer avec le "state" des TVITEM (Nodes)
mon code (subclasser) permet de jouer avec les messages recus par les controles. Ici, tu dois pouvoir intercepter le cochage d'un noeud, et jouer plus finement.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 15 avril 2008 à 16:19
Voici le même algo que vu précédemment, mais utilisant cette fois le subclassing...
Ajoutes ISubclasser.cls et ModSubclasser.bas dans ton projet
Code de Form1 :
Option Explicit
Private Type TVITEM
mask As Long
hItem As Long
state As Long
stateMask As Long
pszText As String
cchTextMax As Long
iImage As Long
iSelectedImage As Long
cChildren As Long
lParam As Long
End Type
Private Const TV_FIRST = &H1100
Private Const TVM_GETNEXTITEM = (TV_FIRST + 10)
Private Const TVM_GETITEMRECT As Long = (TV_FIRST + 4)
Private Const TVM_GETITEMSTATE As Long = (TV_FIRST + 39)
Private Const TVM_GETITEMA As Long = (TV_FIRST + 12)
Private Const TVGN_PARENT As Long = &H3
Private Const TVGN_NEXT = &H1
Private Const TVGN_CHILD = &H4
Private Const TVIF_HANDLE As Long = &H10
Private Const TVIF_STATE As Long = &H8
Private Const TVSIL_STATE As Long = 2
Private Const TVIS_STATEIMAGEMASK As Long = &HF000&
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Implements ISubclasser
Private mtTree As SubClassedWindow
Private Sub Form_Load()
Dim a As Long
Dim b As Long
Dim c As Long
For a = 0 To 5
TreeView1.Nodes.Add Key:="node" & a, Text:="node" & a
For b = 0 To 5
TreeView1.Nodes.Add "node" & a, tvwChild, "node" & a & ";" & b, Text:="node" & a & ";" & b
For c = 0 To 5
TreeView1.Nodes.Add "node" & a & ";" & b, tvwChild, , Text:="node" & a & ";" & b & ";" & c
Next c
Next b
Next a
'SendMessage TreeView1.hWnd, TVM_SETIMAGELIST, TVSIL_STATE, ByVal CcImlState.hImageList
InitiateSubClassing mtTree, Me, TreeView1.hWnd
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
TerminateSubClassing mtTree
End Sub
Private Function ISubclasser_WindowProc(ByVal hWnd As Long, ByVal uMsg As MessageConstants, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tItem As TVITEM
Dim nCheckState As Long
Dim hNode As Long
If uMsg = TVM_SETITEMA Then
CopyMemory tItem, ByVal lParam, 16
If (tItem.mask And TVIF_STATE) = TVIF_STATE Then
If (tItem.stateMask And TVIS_STATEIMAGEMASK) = TVIS_STATEIMAGEMASK Then
nCheckState = (tItem.state And TVIS_STATEIMAGEMASK)
'# Si l'item est coché...
If nCheckState = &H2000& Then
'# On récupère le noeud parent
hNode = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_PARENT, ByVal tItem.hItem)
'# S'il y en a un...
If hNode Then
'# Et on le coche a son tour (qui cochera delui même son noeud parent, et ainsi de suite)
SetItemCheckState hWnd, hNode, &H2000&
End If
ElseIf nCheckState = &H1000& Then
hNode = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_CHILD, ByVal tItem.hItem)
Do While hNode
If GetItemCheckState(hWnd, hNode) = &H2000& Then
tItem.state = (tItem.state Xor nCheckState) Or &H2000&
Exit Do
End If
hNode = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, ByVal hNode)
Loop
End If
CopyMemory ByVal lParam, tItem, 16
End If
End If
End If
ISubclasser_WindowProc = CallOldProc(mtTree, hWnd, uMsg, wParam, lParam)
End Function
Private Function GetItemCheckState(ByVal vhTreeWnd As Long, ByVal vhItem As Long) As Long
Dim tItem As TVITEM
With tItem
.hItem = vhItem
.mask = TVIF_STATE Or TVIF_HANDLE
.stateMask = TVIS_STATEIMAGEMASK
SendMessage vhTreeWnd, TVM_GETITEMA, 0, tItem
GetItemCheckState = (.state And TVIS_STATEIMAGEMASK)
End With
End Function
Private Sub SetItemCheckState(ByVal vhTreeWnd As Long, ByVal vhItem As Long, ByVal vnChecked As Long)
Dim tItem As TVITEM
Dim nCurrentState As Long
With tItem
.hItem = vhItem
.mask = TVIF_STATE Or TVIF_HANDLE
.stateMask = TVIS_STATEIMAGEMASK
SendMessage vhTreeWnd, TVM_GETITEMA, 0, tItem
nCurrentState = .state And TVIS_STATEIMAGEMASK
.state = (.state Xor nCurrentState) Or (vnChecked)
SendMessage vhTreeWnd, TVM_SETITEMA, 0, tItem
End With
End Sub
je n'ai pas intégré les cases grisées... je te laisse le faire.
pour cela, il te suffit simplement de donner la valeur &h3000& au CheckState de ton Item.
ca affichera pour le moment une icone blanche.
pour que ca corresponde a l'icone grisée, a toi de personnaliser les checkboxes, via un controle ImageList.
tu as juste a spécifier l'imagelist utilisé pour les checkbox via la ligne:
SendMessage TreeView1.hWnd, TVM_SETIMAGELIST, TVSIL_STATE, ByVal CcImlState.hImageList
(ici, l'imagelist est CcImlState)
NB: Tout ce qui se trouve dans le code ci-dessus est documenté sur MSDN, n'hesites pas a aller y jeter un oeil
supertoms
Messages postés32Date d'inscriptionjeudi 10 mai 2007StatutMembreDernière intervention27 janvier 2013 16 avril 2008 à 22:50
Merci j'ai hate de tester ça tu es impressionnant !
Mais question :
Je trouve ou ISubclasser.cls et ModSubclasser.bas ? Et je les ajoute ou dans le projet ?
en fait, ce code, c'est ce qui se passe en coulisses, en APIs...
ca nous donne plus de controle que ce que nous permet de faire le controle Treeview, qui encapsule habituellement ces fonctionnalités