什么情况下会用到SetItemData函数
我们在写MFC程序的时候,有时会用到树控件和CTreeView类,我们在生成一棵树之后,希望点击树的一个子节点,然后在右边的对话框或者是List等里面显示这个节点的一个详细信息。这时候,就需要这个树的子节点关联一个变量,可以是下标,可以是地址等等,目的是使得可以方便的找到这个子节点的详细信息,然后显示在别的东西里面。
当然,这只是我自己遇到的一个情形,实际的应用里面,应该有很多相似的可能情况吧。
SetItemData函数的使用也很简单,一个例子:
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()函数取的时候,你就取不到了。
接着就是最后用完了这个东西,要记得释放空间。
因为我们是动态申请的空间,所以在后面不用的时候,要记得自己手动的释放空间。
释放这些空间对应得消息是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;
}
这个函数,会在我们关闭程序或者是关闭树控件这个小的窗口的时候,会自动的调用,包括父子节点一起,一共有多少个,一共就会调用所少次,我先前也看它没有循环,我会担心,它没有完全的释放内存,我就一步一步调试了一遍,确实会把所有的节点都过一遍!大家放心使用。
获取现在鼠标点击的树的子节点
到这里,我标题里面的东西已经结束了,下面是我自己记得另外一个函数,就是在点击树的时候,获取当前的鼠标点击的树的节点,这样才可以显示信息。这是实现里面的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;
}