MFC CTreeView SetItemData()的數據的釋放

什麼情況下會用到SetItemData函數

\qquad我們在寫MFC程序的時候,有時會用到樹控件和CTreeView類,我們在生成一棵樹之後,希望點擊樹的一個子節點,然後在右邊的對話框或者是List等裏面顯示這個節點的一個詳細信息。這時候,就需要這個樹的子節點關聯一個變量,可以是下標,可以是地址等等,目的是使得可以方便的找到這個子節點的詳細信息,然後顯示在別的東西里面。
\qquad當然,這只是我自己遇到的一個情形,實際的應用裏面,應該有很多相似的可能情況吧。
\qquadSetItemData函數的使用也很簡單,一個例子:

void CMyTreeView2::UpdateTree()
{
	CTreeCtrl& tree = GetTreeCtrl();
	HTREEITEM hCChild;
	CMFCApplication3Doc* pDoc = (CMFCApplication3Doc*)GetDocument();
	
	int s = 0;
	for (auto p : pDoc->hoInPar.m_ProjectItemArr)
	{
		if (p->HoleTypeID == 1) {
			//在hChild1節點下面插入hCCild這個節點。
			//節點的信息是pWideChar,它是個CString類型的數據。
			hCChild = tree.InsertItem(pWideChar, hChild1);
			subscript* sub1 = new subscript;
			sub1->i = s;
			tree.SetItemData(hCChild, (DWORD_PTR)sub1);
			//刪除緩衝區
			delete[]buf;
		}
		if (p->HoleTypeID == 2) {
		}
		if (p->HoleTypeID == 10) {
		}
		s++;
	}
}

上面這個例子是我程序中用到的代碼的一個簡化版,主要是爲了使用SetItemData()這個函數,記住兩點:
1.第二個參數要強制轉換。
2.第二個參數一定是堆裏面的,即是new或者是malloc等動態申請的,這一點尤爲重要,我當時就卡在這裏卡了很久。不相信,你就用棧裏面的,然後在後面用GetItemData()函數取的時候,你就取不到了。

接着就是最後用完了這個東西,要記得釋放空間。

\qquad因爲我們是動態申請的空間,所以在後面不用的時候,要記得自己手動的釋放空間。
\qquad釋放這些空間對應得消息是TVN_DELETEITEM.建出來的函數是這樣的,函數名是OnTvnDeleteitem()

void CMyTreeView2::OnTvnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	//reinterpret_cast 強制把 NMHDR類型的指針轉換爲LPNMTREEVIEW類型的指針。
	// TODO: 在此添加控件通知處理程序代碼
	TVITEM& item = pNMTreeView->itemOld;
	if (item.lParam != 0) {
		delete (struct subscript*)item.lParam;
	}
	*pResult = 0;
}

這個函數,會在我們關閉程序或者是關閉樹控件這個小的窗口的時候,會自動的調用,包括父子節點一起,一共有多少個,一共就會調用所少次,我先前也看它沒有循環,我會擔心,它沒有完全的釋放內存,我就一步一步調試了一遍,確實會把所有的節點都過一遍!大家放心使用。

獲取現在鼠標點擊的樹的子節點

\qquad到這裏,我標題裏面的東西已經結束了,下面是我自己記得另外一個函數,就是在點擊樹的時候,獲取當前的鼠標點擊的樹的節點,這樣纔可以顯示信息。這是實現裏面的NM_CLICK消息。

void CMyTreeView2::OnNMClick(NMHDR* pNMHDR, LRESULT* pResult)
{
	// TODO: 在此添加控件通知處理程序代碼
	CTreeCtrl& tree = GetTreeCtrl();
	CPoint CursorPoint;
	if (!GetCursorPos(&CursorPoint))
	{
		return;
	}
	tree.ScreenToClient(&CursorPoint);
	UINT uFlag = 0;
	HTREEITEM select_item = tree.HitTest(CursorPoint, &uFlag);
	if ((NULL != select_item) && (TVHT_ONITEM & uFlag))
	{
		tree.Select(select_item, TVGN_CARET);
	}
	else
	{
		return;
	}
	ShowView(select_item);
	*pResult = 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章