Win32 SDK 下的TreeCtrl控件的封装
自己照着MFC封装,半月前封装了一半,碰到问题就放下了,今天终于封装好了.
[Ctree.h]文件
#pragma once #include <windows.h> #include <commctrl.h> struct MTVINSERTSTRUCT { TVINSERTSTRUCT tvInsert; TCHAR strMid[2500]; }; class CTree { public: CTree(); ~CTree(); HWND m_hWnd; public: //获得树控件的句柄 BOOL GetHwnd(HWND _pHwnd, UINT _idd); //插入树节点 HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct); HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter); //获得选中节点的句柄 HTREEITEM GetSelectedItem()const; //删除选中节点 BOOL DeleteItem(HTREEITEM hItem); //删除所有的节点项 BOOL DeleteAllItem(); //设置节点附加的32位数据 BOOL SetItemData(HTREEITEM hItem, DWORD dwData); //设置节点项数据 BOOL SetItem(TVITEM *pItem); BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam); //获得选中节点项附加的32位数据 DWORD GetItemData(HTREEITEM hItem)const; //获得选中节点项的显示的名称 TCHAR* GetItemText(HTREEITEM hItem)const; //获得选中节点项的图标索引值 BOOL GetItemImage(HTREEITEM hItem, int &nImage, int &nSelectedImage)const; //获得选中节点项的展开状态 BOOL GetItemState(HTREEITEM hItem, UINT nStateMask) const; };
[Ctree.cpp]文件
#include "CTree.h" #include <tchar.h> #include <atlchecked.h> #pragma region MY_CtreeCtrl_Class CTree::CTree() { m_hWnd = NULL; } CTree::~CTree() { } BOOL CTree::GetHwnd(HWND _pHwnd, UINT _idd) { m_hWnd = GetDlgItem(_pHwnd, _idd); if (m_hWnd) { return TRUE; } return FALSE; } HTREEITEM CTree::InsertItem(LPTVINSERTSTRUCT lpInsertStruct) { IsWindow(m_hWnd); return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct); } HTREEITEM CTree::InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) { IsWindow(m_hWnd); TVINSERTSTRUCT lpInsert; lpInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; lpInsert.item.iImage = nImage; lpInsert.item.iSelectedImage = nSelectedImage; lpInsert.item.pszText = (LPWSTR)lpszItem; if (NULL == hParent) hParent = TVI_ROOT; lpInsert.hParent = hParent; lpInsert.hInsertAfter = hInsertAfter; return InsertItem(&lpInsert); } HTREEITEM CTree::GetSelectedItem() const { IsWindow(m_hWnd); return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0); } BOOL CTree::DeleteItem(HTREEITEM hItem) { IsWindow(m_hWnd); return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem); } BOOL CTree::DeleteAllItem() { IsWindow(m_hWnd); return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); } //32位系统可用 BOOL CTree::SetItemData(HTREEITEM hItem, DWORD dwData) { IsWindow(m_hWnd); return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData); }
//64位系统上要用LPARAM 用DWORD要被截断
//***********************************************************************************
BOOL AfxCTreeCtrl::SetItemData(HTREEITEM hItem, LPARAM dwData)
{
ASSERT(IsWindow(m_hWnd));
return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData);
}
//***********************************************************************************
BOOL CTree::SetItem(TVITEM * pItem) { IsWindow(m_hWnd); return (BOOL)SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem); } BOOL CTree::SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) { IsWindow(m_hWnd); TVITEM item; item.hItem = hItem; item.mask = nMask; item.pszText = (LPTSTR)lpszItem; item.iImage = nImage; item.iSelectedImage = nSelectedImage; item.state = nState; item.stateMask = nStateMask; item.lParam = lParam; return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item); } //32位系统可用 DWORD CTree::GetItemData(HTREEITEM hItem) const { IsWindow(m_hWnd); if (NULL == hItem) return 0; TVITEM item; item.hItem = hItem; item.mask = TVIF_PARAM; ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); return item.lParam; } //64位系统用
LPARAM AfxCTreeCtrl::GetItemData(HTREEITEM hItem) const
{
ASSERT(IsWindow(m_hWnd));
TVITEM item;
item.hItem = hItem;
item.mask = TVIF_PARAM;
::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
return (LPARAM)item.lParam;
}
TCHAR* CTree::GetItemText(HTREEITEM hItem) const { IsWindow(m_hWnd); TCHAR* str = new TCHAR[128]; TVITEM item; item.hItem = hItem; item.mask = TVIF_TEXT; item.pszText = str; item.cchTextMax = 128; ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); return str; } BOOL CTree::GetItemImage(HTREEITEM hItem, int &nImage, int &nSelectedImage) const { IsWindow(m_hWnd); TVITEM item = { 0 }; item.hItem = hItem; item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); if (bRes) { nImage = item.iImage; nSelectedImage = item.iSelectedImage; } return bRes; } BOOL CTree::GetItemState(HTREEITEM hItem, UINT nStateMask) const { IsWindow(m_hWnd); TVITEM item = { 0 }; item.hItem = hItem; item.mask = TVIF_STATE; item.stateMask = nStateMask; item.state = 0; ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); return item.state; } #pragma endregion MY_CtreeCtrl_Class
[test.cpp]中测试
HTREEITEM hItem = m_tree.GetSelectedItem(); //TVITEM tvi; //TCHAR szName[20] = { 0 }; ////LPARAM lp = 0; //tvi.mask = TVIF_TEXT | TVIF_PARAM; //tvi.hItem = hItem; //tvi.pszText = szName; //tvi.cchTextMax = sizeof(szName); ////tvi.lParam = lp; //TreeView_GetItem(m_tree.m_hWnd, &tvi); //Stu *pstu = (Stu*)tvi.lParam; //获得选中节点的附加(由SetItemData设置的)数据 /*Stu* pstu = (Stu*)m_tree.GetItemData(hItem); TCHAR *pch = (TCHAR*)m_tree.GetItemData(hItem);*/
//上次在封装这附加数据的时候碰到了问题.
在设置的时候:
TCHAR *pch = new TCHAR;
pch=mid;//mid为要设置的附加数据,类型为TCHAR
m_tree.SetItemData(nItem, (DWORD)pch);
就一直取不出来要的数据,就放下了.今天来看的时候才发现
TCHAR *pch = new TCHAR[128];
_tcscpy_s(pch, 128, mid);
m_tree.SetItemData(nItem, (DWORD)pch);
我用结构体指针为附加数据时,又能正确取出数据.就有点晕菜了,最后才发现.
TCHAR new出来时没给定大小.
正确代码为:
TCHAR *pch = new TCHAR[128];
_tcscpy_s(pch, 128, mid);
m_tree.SetItemData(nItem, (DWORD)pch);
//获得选中节点的Text /*TCHAR *pch = m_tree.GetItemText(hItem); MessageBox(NULL, pch, TEXT("123"), MB_OK);*/ //获得选中节点的图标的索引 /*int nImate, nSelectedImage; m_tree.GetItemImage(hItem, nImate, nSelectedImage);*/ //获得选中节点是否展开,返回0为未展开,非0为展开状态 //UINT n = m_tree.GetItemState(hItem, TVIS_EXPANDED); BOOL m = m_tree.GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED;
释放节点附加数据内存
//5.附加内存的释放 //在子控件通知消息中捕获TVN_DELETEITEM消息 NMHDR *pNMHDR = (NMHDR*)lParam; if (pNMHDR->idFrom == IDC_TREE1 && pNMHDR->code==TVN_DELETEITEM) { NMTREEVIEW *pnmTV = (NMTREEVIEW*)lParam; HTREEITEM hSelItem = pnmTV-> itemNew.hItem; //从lParam参数中获得选中项的句柄 //释放节点附加数据内存 TVITEM item = pnmTV->itemOld; if (item.lParam != 0) { delete (TCHAR*)item.lParam;//删除的数据类型要和前面添加时你附加的数据类型一样, } }