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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章