本文轉載自:VC驿站
https://www.cctry.com/thread-297465-1-1.html
1、控件簡介:
Tree樹形控件也是我們程式設計過程中比較常用的一個控件,而且在其他軟體中也經常能看到,比如Windows系統中的資料總管:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLxMjcihmMyAjcxkmMyIjevZTM0IDMw8CX3EzLcFTM4EDMy8CXtVncvZ2Lc12bj5SeyR3Yj5Cd0F2Lc9CX6MHc0RHaiojIsJye.png)
是以,接下來我就教大家如何來使用這個控件!
2、控件的使用:
a、拖拽Tree樹形控件到對話框模版上;
b、一些常用的屬性:
Check Boxes:結點前是否帶有複選框;
Edit Labels:結點名字是否可編輯;
Has Buttons:父節點是否有+号可供展開;
Has Lines:父子結點之間是否有連接配接線;
Lines At Root:是否從根節點開始就帶有虛線;
等等吧,大家可以根據自己的需要設定相關的屬性。
c、為Tree樹形控件綁定一個 CTreeCtrl 控件類型變量m_Tree;
3、控件的操作:
在樹形控件中每一個結點都有一個句柄(HTREEITEM),同時插入結點時必須提供父結點句柄,(其中根Root結點隻有一個,既不可以添加也不可以删除)利用
HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );
可以插入一個結點,pszItem為顯示的字元,hParent代表父結點的句柄,目前添加的結點會排在hInsertAfter表示的結點的後面,傳回值為目前建立的結點的句柄。
a、添加結點(有多種重載方式,先介紹第一種):
HTREEITEM hRoot = m_Tree.InsertItem(_T("父1"));
HTREEITEM hSub1 = m_Tree.InsertItem(_T("子1"), hRoot);
HTREEITEM hSub2 = m_Tree.InsertItem(_T("子2"), hRoot);
HTREEITEM hSub3 = m_Tree.InsertItem(_T("子子1"), hSub2);
就這樣,可以一層一層的向樹形控件中插入節點。
b、獲得節點的文本:m_Tree.GetItemText(hSub3);
c、設定節點的文本:m_Tree.SetItemText(hSub3, _T("abc"));
d、獲得目前選中的節點:HTREEITEM hSelItem = m_Tree.GetSelectedItem();
e、設定目前選中的節點:m_Tree.SelectItem(hTreeItem);
f、預設上面的情況都是針對單選,那麼Tree樹形控件支不支援多選呢?答案是:預設不支援
不過可以通過給節點前面加上 CheckBox 複選框來解決!下個知識點舉例講解!
備注:那麼不通過CheckBox 能不能實作多選呢?答案也是可以的,不過要寫很多自定義代碼,大家感興趣的話可以看看這幾篇文章,課堂上咱們就不講解了:
http://www.codeguru.com/cpp/cont ... d/article.php/c629/
http://www.codeguru.com/cpp/cont ... d/article.php/c723/
http://www.codeguru.com/cpp/cont ... /article.php/c9219/
g、周遊子節點:
需要用到的相關函數:
HTREEITEM GetRootItem( ); //得到根結點。
HTREEITEM GetChildItem(HTREEITEM hItem); //得到子結點。
HTREEITEM GetPrevSiblingItem/GetNextSiblingItem(HTREEITEM hItem); //得到指明結點的上/下一個兄弟結點。
HTREEITEM GetParentItem(HTREEITEM hItem); //得到父結點。
從根節點開始周遊所有節點,判斷 CheckBox 是否勾選:
void CMFCTestDlg::EnumTreeItem(HTREEITEM hItem)
{
if (!hItem) return;
//先檢測自己是否被勾選
if (m_Tree.GetCheck(hItem))
{
CString strText = m_Tree.GetItemText(hItem);
MessageBox(strText + _T("##勾選了!"));
}
//再周遊所有的子節點
if (m_Tree.ItemHasChildren(hItem))
{
HTREEITEM hChildItem = m_Tree.GetChildItem(hItem);
while (hChildItem)
{
EnumTreeItem(hChildItem);
HTREEITEM hNextItem = m_Tree.GetNextItem(hChildItem, TVGN_NEXT);
hChildItem = hNextItem;
}
}
}
void CMFCTestDlg::OnBnClickedBtnTree()
{
HTREEITEM hRootItem = m_Tree.GetRootItem(); //從根節點開始周遊
EnumTreeItem(hRootItem);
}
h、删除節點、删除所有節點:
m_Tree.DeleteItem(hSub2); //删除節點
m_Tree.DeleteAllItems(); //删除所有節點
i:展開/收起所有節點:
void CMFCTestDlg::ExpandTree(HTREEITEM hItem, UINT nCode)
{
if (!hItem) return;
m_Tree.Expand(hItem, nCode);
if (m_Tree.ItemHasChildren(hItem))
{
HTREEITEM hChildItem = m_Tree.GetChildItem(hItem);
while (hChildItem)
{
ExpandTree(hChildItem, nCode);
HTREEITEM hNextItem = m_Tree.GetNextItem(hChildItem, TVGN_NEXT);
hChildItem = hNextItem;
}
}
}
void CMFCTestDlg::OnBnClickedBtnTree()
{
HTREEITEM hRootItem = m_Tree.GetRootItem(); //從根節點開始周遊
static UINT nCode = TVE_EXPAND;
ExpandTree(hRootItem, nCode);
nCode = (nCode == TVE_EXPAND) ? TVE_COLLAPSE : TVE_EXPAND;
}
j:編輯節點文本:
①、控件的 Edit Labels 屬性設定為 True;
②、響應控件的 TVN_BEGINLABELEDIT 事件:
void CMFCTestDlg::OnTvnBeginlabeleditTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
CEdit *pEdit = m_Tree.GetEditControl();
if (pEdit) pEdit->LimitText(5);//設定編輯框文本長度為5個字元串
*pResult = 0; //繼續
//*pResult = 1; //取消,不繼續編輯,也不觸發 TVN_ENDLABELEDIT
}
③、響應控件的 TVN_ENDLABELEDIT 事件:
void CMFCTestDlg::OnTvnEndlabeleditTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
if (pTVDispInfo && pTVDispInfo->item.pszText && _tcslen(pTVDispInfo->item.pszText))
{
m_Tree.SetItemText(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
}
*pResult = 0;
}
k、插入帶圖示的節點:
這裡面給大家準備幾個ico圖示,供程式使用:
ico.zip
①、将幾個ico圖示檔案添加到工程資源中,ID分别為:IDI_ICON1、IDI_ICON2、IDI_ICON3
②、在對話框類類的頭檔案中加入對象聲明:CImageList m_TreeImage;
③、在對話框的初始化函數中建立圖像清單:BOOL bRet = m_TreeImage.Create(16, 16, ILC_MASK | ILC_COLOR32, 1, 1);
④、添加圖示資源到圖像清單:
int iret = m_TreeImage.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
iret = m_TreeImage.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
iret = m_TreeImage.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
⑤、關聯Tree樹形控件和圖像清單:m_Tree.SetImageList(&m_TreeImage, TVSIL_NORMAL);
⑥、将InsertItem插入節點的代碼改為:
HTREEITEM hRoot = m_Tree.InsertItem(_T("根"), 0, 1);
HTREEITEM hSub1 = m_Tree.InsertItem(_T("子1"), 0, 1, hRoot);
HTREEITEM hSub2 = m_Tree.InsertItem(_T("子2"), 0, 1, hRoot);
HTREEITEM hSub3 = m_Tree.InsertItem(_T("子子3"), 0, 1, hSub2);
這樣就可以啦~!
其中 InsertItem 的第二個參數0和第三個參數1是ico圖示在ImageList中的索引,第二個參數是節點預設的圖示,第三個參數是節點被選中後的圖示。
4、開源控件類:
codeproject 上面關于 Tree樹形控件 的開源控件類可謂是很多啊,這裡面給大家分享一下,需要哪種自己直接拿過去用就行了:
https://www.codeproject.com/Arti ... port-for-HTML-XML-S
https://www.codeproject.com/Arti ... -Supports-Transpare
https://www.codeproject.com/Articles/6597/CDeviceTree
https://www.codeproject.com/Arti ... -select-folders-and
https://www.codeproject.com/Articles/2243/COptionTree
https://www.codeproject.com/Arti ... operty-Tree-Control
https://www.codeproject.com/Arti ... gImage-in-CTreeCtrl
https://www.codeproject.com/Arti ... heckboxes-Supported
https://www.codeproject.com/Arti ... esque-Owner-Drawn-C
https://www.codeproject.com/Arti ... l-that-has-Open-Clo
https://www.codeproject.com/Arti ... Millers-COptionTree
https://www.codeproject.com/Articles/768/CNetworkTreeCtrl
https://www.codeproject.com/Arti ... FX-and-CHourglassFX
https://www.codeproject.com/Articles/2913/A-Tree-List-Control
https://www.codeproject.com/Arti ... wn-TreeList-Control
https://www.codeproject.com/Arti ... th-ToolTip-Based-On
https://www.codeproject.com/Arti ... ontrol-with-Columns
5、小作業:
①、給Tree樹形控件添加右鍵彈出菜單,菜單中有個複制的菜單項,點選可以複制結點的文本;
②、點選控件的 CheckBox 後,實際上目前選中的結點不是我點選的結點,能否做到勾選CheckBox 之後,就選中該結點;
③、實作三态CheckBox,可以直接找開源類來實作:https://www.codeproject.com/Articles/847799/CQuadStateTree
具體操作細節見視訊教程的示範和講解!
第15課免費試看,下載下傳位址:
https://www.cctry.com/thread-297465-1-1.html