什麼情況下會用到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;
}