Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour,
Je personnalise un TreeView (je rapelle que je suis en PB 8.04 et j'uitilise les PFC) avec des cases a cocher sur les items.
Lorsque un clic est effectué sur un Item, je decoche tous les enfants et tous les parents.
Mon algo se trouve donc dans la fonction clicked du treeView.
Je me rend compte maintenant que lorsqu'on clique sur le label de l'item et non la case a cocher, il passe dans l'evenement clicked (et effecue donc mon algo), sans cocher ou decocher la case de l'item en question.
Pour quelles raisons?
Hors ligne
Envoies le script de ton évènement Clicked().
Hors ligne
Voila, mais comme je l'ai di, le probleme ne vient pas de mon code mais du fait qu'il passe par l'evt clicked sans modifier le StatePictureIndex de l'item.
// Quant il clique sur l'item pour le cocher, ca coche tout // Quant il le decoche, ca ne modifie pas les autres long ll_ret, ll_handle TreeViewItem item // On commence par deployer tou l'arbre a partir du handle this.expandall(handle) ll_ret = this.getItem(handle,item) // On regarde s'il est coché ou décoché if item.StatePictureIndex = 1 then // décoché // On applique la fonction sur ses fils pour ne pas changer son statut 2 fois ll_handle = this.FindItem(ChildTreeItem!,handle) // Puis tant qu'il y a des voisins a l'enfant, on les coche do while ll_handle <> -1 ll_ret = this.getItem(ll_handle,item) // Récursivité sur les enfants of_cocheaccess(ll_handle) ll_handle = this.FindItem(nextTreeItem!,ll_handle) loop else // coché // On applique la fonction sur ses fils pour ne pas changer son statut 2 fois ll_handle = this.FindItem(ChildTreeItem!,handle) // Puis tant qu'il y a des voisins a l'enfant, on les coche do while ll_handle <> -1 ll_ret = this.getItem(ll_handle,item) // Récursivité sur les enfants of_decocheaccess(ll_handle) ll_handle = this.FindItem(nextTreeItem!,ll_handle) loop // Partie importante : Quant on decoche un item, on doit decocher tous // ses parents cochés ll_handle = this.FindItem(ParentTreeItem!,handle) do while ll_handle <> -1 ll_ret = this.getItem(ll_handle,item) if item.StatePictureIndex = 2 then // S'il est coché, on decoche item.StatePictureIndex = 1 this.setItem(ll_handle,item) end if ll_handle = this.FindItem(ParentTreeItem!,ll_handle) LOOP end if
Hors ligne
J'ai l'impression que ton script ne traite pas le "cochage/decochage" de l'item clické.
Il me semble (mais je ne suis pas sur à 100%) que lorsque tu clickes directement sur le noeud c'est le système qui prend en charges le changement d'état, par contre quand tu cliques sur la label il ne fait que sélectionné l'item sans changer son état (pour cela il faut doubleclick sur le label). Il faut donc ajouter le cochage/décochage de l'item clické dans ton algo si c'est le label et non le noeud qui est clické.
Hors ligne
il y a une histoire de hierarchie dans le treeview.
tu peux faire un test, pour voir sur quelle branche se trouve le clic...
Hors ligne
par exemple...
tv.FindItem(CurrentTreeItem! , 0)
Hors ligne
Oui Chrnico c'est exactement ca.
Mais comment savoir si c'est le label ou le noeud qui a été cliqué?
Hors ligne
mial a écrit:
Oui Chrnico c'est exactement ca.
Mais comment savoir si c'est le label ou le noeud qui a été cliqué?
Désolé, ça fait un bout de temps que j'ai touché à un treeview.
Est-ce que lorsque tu clickes sur le noeud la propriété Selected est positionnée à True sur le TreeviewItem ?
Parce que si ce n'est pas le cas c'est gagné !
Sur le clicked, il suffit alors de vérifier si l'item est selected : si oui => label, sinon => noeud
Hors ligne
tu pourrais mettre le script qui permet de construire le contenu de ta treeview ?
Hors ligne
Désolé, ça fait un bout de temps que j'ai touché à un treeview.
Est-ce que lorsque tu clickes sur le noeud la propriété Selected est positionnée à True sur le TreeviewItem ?
Parce que si ce n'est pas le cas c'est gagné !
Sur le clicked, il suffit alors de vérifier si l'item est selected : si oui => label, sinon => noeud
Nan je ne peux pas différencier les 2. La propriété selected est a false dans les 2 cas si l'item n'etait pas séléctionné précédement et inversement s'il l'était.
Par contre, apres etre passé l'evt clicked (et donc mon code), lorsque j'ai cliqué sur le label, il me selectionne l'item donc selected = TRUE alors que pour un clic sur le noeud, l'item n'est pas séléectionné : selected = false
Mais j'ai besoin de l'info au moment de l'evt clicked.
Le code de mon constructeur, mais encore une fois le pb n'est pas spécifique à mon code :
// On construit le tree view... // On crée l'arborescence dans l'ordre : // - Global // - Societe // - Parc // - Groupe // - Utilisateur // Declarations long ll_row, ll_i, ll_handleroot, ll_row2, ll_h, ll_j, ll_handlesociete long ll_handleparc, ll_row3, ll_handlegroup, ll_row4, ll_k string ls_nosociete, ls_noparc, ls_group, ls_user, ls_intitule TreeViewItem item // On ajoute les images : this.addPicture('deca.ico') this.addPicture('Groupe.ico') this.addPicture('m_16_affectation.ico') // On commence par ajouter l'item global au treeView item.Label = "Global" item.PictureIndex = 1 ll_handleroot = this.insertitemFirst(0,item) // Puis ajout des sociétés n_ds lds_dw n_ds lds_dw2 n_ds lds_dw3 n_ds lds_dw4 lds_dw = create n_ds lds_dw2 = create n_ds lds_dw3 = create n_ds lds_dw4 = create n_ds lds_dw.DataObject= "d_societe" lds_dw.settransobject(SQLCA) lds_dw2.DataObject= "d_parc" lds_dw2.settransobject(SQLCA) lds_dw3.DataObject= "d_group" lds_dw3.settransobject(SQLCA) lds_dw4.DataObject= "d_users" lds_dw4.settransobject(SQLCA) ll_row = lds_dw.retrieve() // Pour toutes les societes For ll_i = 1 to ll_row ls_nosociete = lds_dw.getItemString(ll_i,"no_societe") ls_intitule = lds_dw.getItemString(ll_i,"intitule") // Si pas d'intitulé, on met le code if Trim(ls_intitule) = "" then ls_intitule = ls_nosociete end if item.label = ls_intitule item.data = ls_nosociete ll_handlesociete = this.insertItemLast(ll_handleroot,item) // Tous les parcs pour cette societe ll_row2 = lds_dw2.retrieve(ls_nosociete) // Pour tous les parcs For ll_j = 1 to ll_row2 ls_noparc = lds_dw2.getItemString(ll_j,"no_parc") ls_intitule = lds_dw2.getItemString(ll_j,"intitule") // Si pas d'intitulé, on met le code if Trim(ls_intitule) = "" then ls_intitule = ls_noparc end if item.label = ls_intitule item.data = ls_nosociete + ls_noparc ll_handleparc = this.insertItemLast(ll_handlesociete,item) // Tous les groupes pour ce parc ll_row3 = lds_dw3.retrieve(ls_nosociete + ls_noparc + '%',1) // Pour tous les groupes For ll_h =1 to ll_row3 ls_group = lds_dw3.getItemString(ll_h,"name") ls_intitule = lds_dw3.getItemString(ll_h,"description") if Trim(ls_intitule) = "" then ls_intitule = ls_group end if item.label = ls_intitule item.data = ls_group ll_handlegroup = this.insertItemLast(ll_handleparc,item) // Pout tous les users ll_row4 = lds_dw4.retrieve(ls_group) For ll_k =1 to ll_row4 ls_user = lds_dw4.getItemString(ll_k,"user_name") ls_intitule = Right(ls_user,Len(ls_user) - 8) item.label = ls_intitule item.data = ls_user this.insertItemLast(ll_handlegroup,item) next next next next // On expand tout this.expandall(ll_handleroot) // On grise selon ses droits destroy lds_dw destroy lds_dw2 destroy lds_dw3 destroy lds_dw4
Hors ligne
mial a écrit:
Mais j'ai besoin de l'info au moment de l'evt clicked.
tu peux toujours faire un post... (même si je n'aime pas beaucoup)
Hors ligne
Changement important dans le traitement. Je viens de me rendre compte qu'en appuyant sur la barre d'espace une fois un item selectionné, l'evt clicked n'est pas parcouru.
Je ne dois donc pas modifier l'evt clicked mai en créer un gérant le cochage d'un noeud (par le clic ou la bar d'espace), ce qui contournera mon probleme precedent.
Seulement je ne vois vraiment pas comment faire, je n'ai pas trouvé d'id event correspondant.
Hors ligne
Fenêtre, Event key, pbm_keydown
If key = KeySpaceBar! Then // traitement End If Return 0
Hors ligne
pour savoir si tu es sur le noeud ou pas...
tu places une variable d'instance
genre long il_noeud[]
et dans la construction de la treeview,
ll_handlesociete = this.insertItemLast(ll_handleroot,item)
il_noeud[upperbound(il_noeud) + 1] = ll_handlesociete
dans l'evenement clicked
tu n'as pas plus qu'à faire ce test...
long ll_handle, ll_i boolean lb_noeud lb_noeud = false ll_handle = this.FindItem(CurrentTreeItem! , 0) for ll_i = 1 to upperbound(il_noeud) if il_noeud[ll_i] = ll_handle then lb_noeud = true exit end if next if lb_noeud then // voila, on est dans la noeud.... end
Hors ligne
eRaSorZ : Ca me permet de gérer la barre d'espace mais pour un clic sur l'item, je reviens à mon problème de départ.
pick ouic : je recupere le handle dans l'event clicked que j'ai cliqué sur le noeud ou sur le label. J'en reviens tjrs au meme probleme.
Hors ligne
mial a écrit:
eRaSorZ : Ca me permet de gérer la barre d'espace mais pour un clic sur l'item, je reviens à mon problème de départ.
Dans le IF tu peux toujours faire un post event d'une event où tu teste le selected de l'item.
C'est également cet event que tu appeleras du clicked
Hors ligne
Et dans le cas où on clic sur un item qui était deja selectionné?
Hors ligne
mial a écrit:
Et dans le cas où on clic sur un item qui était deja selectionné?
Puisque tu connais l'état avant le click utilisateur (dans l'event clicked) et après (ton event perso posté) tu es à même de savoir si l'état à changé ou pas et donc si c'est le label ou le noeud sur lequel tu as clické...
Hors ligne
Pb résolu grâce aux API windows qui determine si le clic de souris s'est fait sur une case à cocher...balaise le colegue!
Hors ligne
bon, la moindre des choses, c'est de nous expliquer ta solution...
tu ne veux pas partager tes sources ? tu fais encore ton timide ?
Hors ligne
désolé je n'avais pas vu le post précédent.
Alors voila les sources exactes :
2 structures :
os_point : long l_x et long l_y os_tvhittestinfo : long l_flags, long l_hitem, os_point str_point
2 variable d'instances :
long ii_xpos long ii_ypos
Ajout d'une exteral function :
FUNCTION long HitMsg( long hWindow, uint uMsg, long wParam, REF OS_TVHITTESTINFO lParam ) LIBRARY "user32.dll" ALIAS FOR SendMessageA
Création d'un event ue_mousemove avec l'id pbm_mousemove:
ii_xpos = xpos ii_ypos = ypos
puis surcharge de l'Event clicked :
constant unsignedinteger TVM_HITTEST = 4369 constant unsignedinteger TVHT_ONITEMSTATEICON = 64 /*====> Variables locales <====*/ // Structure spéciale treeview OS_TVHITTESTINFO lstr_tvhittest /*====> Vérifications <====*/ // Alimentation de la structure lstr_tvhittest.str_point.l_x = UnitsToPixels( ii_xpos, XUnitsToPixels! ) lstr_tvhittest.str_point.l_y = UnitsToPixels( ii_ypos, YUnitsToPixels! ) HitMsg(Handle(this), TVM_HITTEST, 0, lstr_tvhittest ) // Si on n'est au niveau de la stateicon, on transmet l'événement if lstr_tvhittest.l_hItem <> 0 then if ( lstr_tvhittest.l_flags = TVHT_ONITEMSTATEICON ) then this.event ue_stateicon_changing(handle) end if end if
et enfin la barre d'espace avec l'event keydown :
/*====> Recherche de l'appuie sur la barre d'espace <====*/ if keyflags = 0 and key = KeySpaceBar! then this.event ue_stateicon_changing(this.FindItem(CurrentTreeItem!, 0)) end if
Voila apres on met son code dans ue_stateicon_changing..En voila du bon boulot, balaise le collegue!
Dernière modification par mial (17-07-2007 12:19:46)
Hors ligne
Merci Mial pour ce code.
20 pépites pour toi (but don't forget code = pb next time please!)
Hors ligne