1. 程式人生 > >MFC TreeControl複選框:選中某個節點的複選框後,自動選中子節點的複選框

MFC TreeControl複選框:選中某個節點的複選框後,自動選中子節點的複選框

1、實現選中TreeControl中的某個複選框,子節點的複選框自動選中:



2、如上例,當點選根節點Windows前的複選框時,它的所有子節點前面的複選框都被選中;

3、實現該功能的思路是:當用戶勾選某個複選框時,遍歷該節點的子節點,將所有的子節點複選框狀態改為和點選複選框的狀態(點選後)一致;其中有兩個實現的難點:

(1)如何確定使用者勾選了複選框,以及具體勾選了那個複選框;

(2)如何改變所有子節點的複選框;沒有什麼好辦法,只有通過遍歷,然後一項一項的修改;在此提一點,如果TreeControl的節點可能很多,最好不要用遞迴演算法,以防止棧溢位;

(3)最後一點,只要編寫程式碼都會發現,在此提一下:

那就是,在NM_CLICK訊息的響應函式中是,雖然滑鼠點選了某個複選框,但是此時該複選框的狀態實際上還沒改變;

注意:滑鼠點選CheckBox時,訊息的順序是 NM_CLICK —> LVN_ITEMCHANGED,即CheckBox的狀態是在 NM_CLICK訊息函式結束後才會發生變化,在NM_CLICK中使用GetCheck無效(或者說獲得的複選框狀態是相反的)。

4、關鍵程式碼:用棧實現的遍歷函式:

int ChildNodeChanged(HTREEITEM hitemNode, BOOL nState)
{
	stack <HTREEITEM> stackTreeItem;
	HTREEITEM hitemNext = m_ctlTree.GetChildItem(hitemNode);
	stackTreeItem.push(hitemNext);

	while ( !stackTreeItem.empty() )
	{
		hitemNext = stackTreeItem.top();
		stackTreeItem.pop();

		while ( hitemNext != NULL )
		{
			if ( nState == BST_CHECKED )
			{
				m_ctlTree.SetCheck(hitemNext);
			}
			else
			{
				m_ctlTree.SetCheck(hitemNext, BST_UNCHECKED);
			}

			HTREEITEM hitemChild = m_ctlTree.GetChildItem(hitemNext);
			if ( hitemChild != NULL )
			{
				stackTreeItem.push(hitemChild);
			}

			hitemNext = m_ctlTree.GetNextItem(hitemNext, TVGN_NEXT);
		}
	}

	return 0;
}