代碼運行效果圖如下:
一、樹控制(CTree Control)
樹控制用於顯示具有一定層次結構的數據項。很多應用程序都使用該控件,例如資源管理器中的磁盤目錄等。
樹控制中有根數據項(root item),根數據項下包含各個子數據項(child item)。根數據項是所有子數據項的父親,而這些子數據項是根數據項的孩子。所有子數據項互為兄妹(sibling)關系。每個數據項包括數據項名稱(文本字符串)和用於表示該數據項的圖像,每個數據項下還可以包含子項,整個結構就象一棵樹。
二、使用樹控制
在MFC中,樹控制被封裝成CTreeCtrl類。下面我們談談樹控制的創建、屬性和操作方法。
(1) 樹控制的創建
樹控制一般用於對話框程序。創建樹控制有兩種方法,一種是靜態創建,一種是動態創建。靜態創建是指拖放控件後聲明與之相關的成員變量來操作樹控制。在對話框程序界面上拖放一個CTreeCtrl控件,然後通過ClassWizard添加一個CTreeCtrl類型的成員變量並在程序中使用它。動態創建是指在程序中使用Create函數創建樹控制對象。本文例子采用靜態創建的方法。
(2) 樹控制的屬性
樹控制有很多屬性操作函數。使用這些函數可以得到樹控制的各種屬性信息。例如:取得樹控制中項數GetCount、取得樹控制中項相對於父項的偏移值GetIndent、取得樹控制圖像列表控制句柄GetImageList等。具體信息可以查看MSDN幫助。
(3) 數控制的操作
樹控制的操作方法包括插入一個樹項InsertItem、刪除一個樹項DeleteItem、刪除
所有樹項DeleteAllItems、展開或合攏樹項的子項Expand、選中特定樹項
SelectItem、選擇一個樹項作為第一個可視樹項SelectSetFirstVisible、編輯一個可
視的樹項EditLabel和排序給定父樹項的子樹項SortChildren等。
三、讓樹控制支持數據項查找功能
在有些場合下用戶需要在樹控制中添加新的數據項。新添加的數據項可能和已有的某數據項名稱重復。為避免這種情況,我們需要一個函數它能夠在添加新數據項之前先檢查所有的數據項,如果查到包含新添加數據項名稱的數據項已存在,可以向用戶提示該信息。使用遞歸方法來實現該函數相對簡單。
下面是該函數的原型、參數及代碼。
/***************************************************************
*
* 名稱:FindItem
*
* 功能:在樹控制中根據數據項名稱查找數據項
*
* 參數:item - 要查詢的數據項及其子數據項
*
* strText - 要查詢的數據項名稱
*
* 返回值:NULL - 沒找到
*
* (非空的HTREEITEM ) - 找到
*
***************************************************************/
HTREEITEM CTreeCtrlEx::FindItem(HTREEITEM item, CString strText)
{
HTREEITEM hFind;
if(item == NULL)
return NULL;
while(item!=NULL)
{
if(GetItemText(item) == strText)
return item;
if(ItemHasChildren(item))
{
item = GetChildItem(item);
hFind = FindItem(item,strText);
if(hFind)
{
return hFind;
}
else
{
item= GetNextSiblingItem(GetParentItem(item));
}
}
else
{
item = GetNextSiblingItem(item);
if(item==NULL)
return NULL;
}
}
return item;
}
四、示例程序
我們創建一個對話框程序。
(1) 通過“FILE->NEW->PROJECTS->MFC AppWizard(EXE)”建立名為MyTreeCtr的
工程,在建立過程中選擇基於對話框(Dialog based)的應用;
(2) 將對話框中的默認按鈕控件“確定”刪除,並將所有對話框屬性中的Language域設置為Chinese(P.R.C.),以使應用程序支持中文;在對話框窗口中添加樹控制對象(TREE CONTROL),並設置一個按鈕“新建數據項”,其對應標識分別如下:
控制名稱 標題名稱 標識符號 對應成員變量或函數 樹控制 IDC_MYTREE CTreeCtrl m_ctrlTree 按鈕 新建數據項 IDC_ NEWITEM OnNewitem() 樹控制項目 HTREEITEM m_hInsertItem
(3) 處理樹控制的TVN _BEGINLABELEDIT和TVN _ENDLABELEDIT消息,CMyTreeCtrlDlg增加OnBeginlabeleditMytree和OnEndlabeleditMytree兩個處理函數。
void CMyTreeCtrlDlg::OnBeginlabeleditMytree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
m_ctrlTree.GetEditControl()->LimitText(16);
*pResult = 0;
}
void CMyTreeCtrlDlg::OnEndlabeleditMytree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
CString strName;
m_ctrlTree.GetEditControl()->GetWindowText(strName);
if(strName.IsEmpty())
{
AfxMessageBox(_T("數據項名稱不能為空,請重新輸入!"));
CEdit* pEdit = m_ctrlTree.EditLabel(m_hInsertItem);
ASSERT(pEdit != NULL);
return;
}
HTREEITEM hRoot = m_ctrlTree.GetRootItem();
HTREEITEM hFind = m_ctrlTree.FindItem(hRoot,strName);
if(hFind==NULL)
{
char msg[64]={0};
sprintf(msg,"新添加數據項名稱 %s ,確定嗎?",strName);
if(MessageBox(msg,_T("提示"),MB_OKCANCEL) == IDOK)
*pResult = TRUE;
else
m_ctrlTree.DeleteItem(m_hInsertItem);
}
else
{
AfxMessageBox(_T("該數據項已存在,請重新輸入!"));
CEdit* pEdit = m_ctrlTree.EditLabel(m_hInsertItem);
ASSERT(pEdit != NULL);
*pResult = 0;
}
}
五、結束語
CTreeCtrlEx類的FindItem函數實現數據項查找的功能。測試程序在Win98+VC6.0環境下測試通過。