This article (2008.10.17) describes how to connect ihtmldomnode with ihtmldomchildrencollection and use it.
- The DOM tree class used to display web pages, inherited from ctreectrl -- source file
- // Domtree. cpp: implementation file
- # Include "stdafx. H"
- # Include "domtree. H"
- # Include <queue>
- # Define idm_expandall 10001
- # Define idm_collapseall 10002
- Implement_dynamic (cdomtree, ctreectrl)
- Begin_message_map (cdomtree, ctreectrl)
- On_policy_reflect (tvn_deleteitem, ontvndeleteitem)
- On_wm_destroy ()
- On_policy_reflect (tvn_selchanged, ontvnselchanged)
- On_command (idm_expandall, onexpandall)
- On_command (idm_collapseall, oncollapseall)
- On_wm_rbuttondown ()
- End_message_map ()
- Void cdomtree: ontvndeleteitem (nmhdr * pnmhdr, lresult * presult)
- {
- Lpnmtreeview pnmtreeview = reinterpret_cast <lpnmtreeview> (pnmhdr );
- Tvitem * pitem = & pnmtreeview-> itemold;
- If (pitem & pitem-> lparam)
- {
- Iunknown * pnodeunknown = reinterpret_cast <iunknown *> (pitem-> lparam );
- # If defined (_ Debug)
- Long relcnt = pnodeunknown-> release (); // For addref when added to the tree item data
- Atlassert (relcnt = 0 );
- # Else
- Pnodeunknown-> release ();
- # Endif
- }
- * Presult = 0;
- }
- Void cdomtree: ondestroy ()
- {
- Ctreectrl: ondestroy ();
- }
- Void cdomtree: updatedom (ihtmldocument2 * pdoc)
- {
- Setredraw (false );
- Deleteallitems ();
- M_spdoc2 = pdoc;
- Preparedomtree ();
- Setredraw (true );
- }
- // A breadth first tree creating algorithm
- Bool cdomtree: preparedomtree ()
- {
- Ccomqiptr <ihtmldocument3> spdoc3 = m_spdoc2;
- Bool Bret = spdoc3! = NULL;
- If (! Bret ){
- Atlassert (0 );
- Return Bret;
- }
- Ccomptr <ihtmlelement> sprootelement;
- Bret = succeeded (spdoc3-> get_documentelement (& sprootelement ));
- If (! Bret) return Bret;
- Ccomqiptr <ihtmldomnode> sprootnode = sprootelement;
- Bret = sprootnode! = NULL;
- If (! Bret) return Bret;
- STD: queue
- STD: queue <ccomqiptr <ihtmldomnode> queue_domnodes;
- Queue_domnodes. Push (sprootnode );
- Queue_tree_nodes.push (tvi_root );
- While (! Queue_tree_nodes.empty ())
- {
- Ccomqiptr <ihtmldomnode> spdomnode = queue_domnodes.front ();
- Htreeitem parent = queue_tree_nodes.front ();
- Queue_domnodes.pop ();
- Queue_tree_nodes.pop ();
- Htreeitem thisnode = insertdomnode (spdomnode, parent );
- Ccomptr <idispatch> spcollectiondispatch;
- If (succeeded (spdomnode-> get_childnodes (& spcollectiondispatch )))
- {
- Long numchildren = 0;
- Ccomqiptr <ihtmldomchildrencollection> spcollection = spcollectiondispatch;
- If (!! Spcollection)
- {
- Spcollection-> get_length (& numchildren );
- For (long I = 0; I <numchildren; I ++)
- {
- Ccomptr <idispatch> spitemdispatch;
- Spcollection-> item (I, & spitemdispatch );
- If (!! Spitemdispatch)
- {
- Ccomqiptr <ihtmldomnode> spitemnode = spitemdispatch;
- If (!! Spitemnode)
- {
- Queue_domnodes.push (spitemnode );
- Queue_tree_nodes.push (thisnode );
- }
- }
- }
- }
- }
- }
- Return Bret;
- }
- Htreeitem cdomtree: insertdomnode (ihtmldomnode * pinode, htreeitem hparent)
- {
- Ccomptr <idispatch> spcollectiondispatch;
- Ccomptr <ihtmldomnode> spnode (pinode );
- Ccombstr nodename;
- TV _insertstruct Tvis;
- Tvis. hparent = hparent;
- Tvis. hinsertafter = tvi_last;
- Tvis. item. Mask = tvif_text | tvif_param;
- If (succeeded (spnode-> get_nodename (& nodename )))
- {
- Cstring strnodename (nodename );
- Tvis. item. psztext = strdup (strnodename );
- }
- // Need to addref because we'll be keeping interface pointer As Treeview item data
- Pinode-> addref ();
- Tvis. item. lparam = reinterpret_cast <lparam> (pinode );
- Htreeitem hthisitem = insertitem (& Tvis );
- If (hthisitem = NULL)
- {
- Pinode-> release ();
- Return NULL;
- }
- Return hthisitem;
- }
- Void cdomtree: ontvnselchanged (nmhdr * pnmhdr, lresult * presult)
- {
- Lpnmtreeview pnmtreeview = reinterpret_cast <lpnmtreeview> (pnmhdr );
- Tvitem * pitem = & pnmtreeview-> itemnew;
- Ihtmldomnode * pdomnode = reinterpret_cast <ihtmldomnode *> (pitem-> lparam );
- * Presult = 0;
- }
- Void cdomtree: onexpandall ()
- {
- Expandall ();
- }
- Void cdomtree: oncollapseall ()
- {
- Collapseall ();
- }
- Void cdomtree: onrbuttondown (uint nflags, cpoint point)
- {
- Cmenu context;
- Context. createpopupmenu ();
- Clienttoscreen (& Point );
- Context. appendmenu (mf_string | mf_enabled, idm_expandall, _ T ("Expand All "));
- Context. appendmenu (mf_string | mf_enabled, idm_collapseall, _ T ("collapse all "));
- Context. trackpopupmenu (tpm_leftalign | tpm_leftbutton | tpm_rightbutton, point. X, point. Y, this );
- Ctreectrl: onrbuttondown (nflags, point );
- }
- Void cdomtree: expandall ()
- {
- Htreeitem hcurrent = getselecteditem ();
- If (! Hcurrent)
- Hcurrent = getrootitem ();
- If (hcurrent)
- {
- Setredraw (false );
- // When expanding we must expand parent before its children
- Unsigned int flags = doparentfirst;
- Doforitemandchildren (hcurrent, expanditem, flags );
- Ensurevisible (hcurrent );
- Setredraw (true );
- }
- }
- // Recursive helper that calla method, that Param FP points to, for a hparent Node
- // And all of its children, its children's children, etc.
- // This is one of few cases where I used-> * notation for method call through a pointer
- Void cdomtree: doforitemandchildren (htreeitem hparent, foreachitem FP, unsigned int flags/* = 0 */)
- {
- // Doparentfirst flag tells us if we want FP to be called on parent node first, then children, or viceversa
- If (flags & doparentfirst)
- {
- If (! (Flags & skiptopparent ))
- (This-> * FP) (hparent );
- }
- Htreeitem hchild = getchilditem (hparent );
- While (hchild)
- {
- Doforitemandchildren (hchild, FP, (flags & doparentfirst )? Doparentfirst: 0 );
- Hchild = getnextsiblingitem (hchild );
- };
- If (! (Flags & doparentfirst ))
- {
- If (! (Flags & skiptopparent ))
- (This-> * FP) (hparent );
- }
- }
- Void cdomtree: collapseall ()
- {
- Htreeitem hcurrent = getselecteditem ();
- If (! Hcurrent)
- Hcurrent = getrootitem ();
- If (hcurrent)
- {
- Setredraw (false );
- Expand (hcurrent, tve_collapse );
- Setredraw (true );
- }
- }