複製鏈接
請複製以下鏈接發送給好友

CTreeCtrl

鎖定
樹控件(CTreeCtrl)主要用來顯示具有一定層次結構的數據項,如資源管理器中的磁盤目錄等,以供用户在其中進行各種選擇。
中文名
樹控件
外文名
CTreeCtrl
功    能
顯示具有一定層次結構的數據項
例    如
資源管理器中的磁盤目錄等

CTreeCtrl簡介

樹控制中的每個數據項包括數據項名稱的文本字符串和用於表示該數據項的圖像,每個數據項下面均可包含各種子項,整個結構就象目錄樹一樣。對於包含各種子項的數據項,可通過鼠標雙擊來展開或合攏,這可以通過控制樹的不同風格來實現樹控制的不同顯示形態。

CTreeCtrl詳細資料

CTreeCtrl建立控件

CtreeCtrl&treeCtrl 建立樹控件對象結構
Create 建立樹控件並綁定對象
樹控件CTreeCtrl::Create的調用格式如下:
BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
其中參數dwStyle用來確定樹控件的類型;rect用來確定樹控件的大小和位置;pParentWnd用來確定樹控件的父窗口,通用是一個對話框並且不能為NULL;nID用來確定樹控件的標識。樹控件的風格可以是下列值的組合:
TVS_HASLINES 表示樹控件在各子項之間存在連線;
TVS_LINESATROOT 表示樹控件在根項之間存在連線;
TVS_HASBUTTONS 表示樹控件視在父項左側存在展開合攏控件按鈕;
TVS_EDITLABELS 表示可以控件鼠標單擊修改樹項的名稱;
TVS_SHOWSELALWAYS 表示選中項即使在窗口失去輸入焦點時仍然保持選中狀態;
TVS_DISABLEDRAGDROP表示禁止樹控件發送TVN_BEGINDRAG消息

CTreeCtrl控件屬性

樹控件屬性類包括取得樹控件中項數GetCount、取得樹控件中項相對於父項的偏移值GetIndent、取得樹控件圖像列表控件句柄GetImageList、設置樹控件圖像列表控件句柄SetImageList、取得匹配下一個樹項GetNextItem、判斷給定樹項是否包含子項ItemHasChildren、取得樹項子項GetChildItem、取得下一個同屬樹項GetNextSiblingItem、取得前一個同屬樹項GetPrevSiblingItem、取得父樹項GetParentItem、取得第一個可視樹項GetFirstVisibleItem、取得下一個可視樹項GetNextVisible Item、取得前一個可視的樹項GetPrevVisibleItem、取得被選中的樹項GetSelectedItem、取得根樹項GetRootItem、取得樹項的屬性GetItem、設置樹項的屬性SetItem、取得樹項的狀態GetItemState、設置樹項的狀態SetItemState、取得與樹項關聯圖像GetItemImage、設置與樹項關聯圖像SetItemImage、取得樹項文本GetItemText、設置樹項文本SetItemText和取得樹項編輯控件句柄GetEditControl等。

CTreeCtrl操作方法

樹控件的操作方法包括插入一個樹項InsertItem、刪除一個樹項DeleteItem、刪除所有樹項DeleteAllItems、展開或合攏樹項的子項Expand、選中特定樹項SelectItem、選擇一個樹項作為第一個可視樹項SelectSetFirstVisible、編輯一個可視的樹項EditLabel和排序給定父樹項的子樹項SortChildren等。

CTreeCtrl數據結構

在使用樹控件時需要了解兩個個非常重要的數據結構TV_ITEM和TV_INSERTSTRUCT,前一個數據結構是用來表示樹控件的樹項信息,後一個數據結構是用來定義將樹項增加到數據控件中所需要的數據內容。另外,還需要NM_TREEVIEW、TV_DISPINFO和TV_HITTESTINFO三個數據結構,這幾個數據結構的定義方法如下:
①基本數據項結構
typedef struct _TV_ITEM {
UINT mask; //結構成員有效性屏蔽位
HTREEITEM hItem; //數據項控件句柄
UINT state; //數據項狀態
UINT stateMask; //狀態有效性屏蔽位
LPSTR pszText; //數據項名稱字符串
int cchTextMax; //數據項名稱的最大長度
int iImage; //數據項圖標索引號
int iSelectedImage;//選中數據項圖標索引號
int cChildren; //子項標識
LPARAM lParam; //程序定義的32位數據
} TV_ITEM, FAR *LPTV_ITEM;
②插入樹項結構
typedef struct _TV_INSER TSTRUCT {
HTREEITEM hParent; //父項控件句柄
HTREEITEM hInsertAfter; //插入樹項的位置
TV_ITEM item; //數據項的結構
} TV_INSERTSTRUCT, FAR *LPTV_INSERTSTRUCT;
其中插入的位置如果是TVI_FIRST 或TVI_LAST ,則分別插入到樹控件的最前面或最後面,如果是TVI_SORT ,則插入的樹項自動插入到合適的位置。
③樹控件通知消息結構
typedef struct _NM_TREEVIEW {
NMHDR hdr; //通知消息句柄
UINT action; //通知消息標誌
TV_ITEM itemOld; //原來的數據結構
TV_ITEM itemNew; //新的數據結構
POINT ptDrag; //拖動指針
} NM_TREEVIEW;
④取得或設置數據結構
typedef struct _TV_DISPINFO { tvdi
NMHDR hdr; //通知消息控件句柄
TV_ITEM item; //數據項結構
} TV_DISPINFO;
⑤指針測試數據結構
typedef struct _TVHITTESTINFO { tvhtst
POINT pt; //客户區域屏幕座標指針
UINT flags; //存放測試結果的變量
HTREEITEM hItem; //測試的數據項結構
} TV_HITTESTINFO, FAR *LPTV_HITTESTINFO;
其中flags測試結果可以是如下值:
TVHT_ABOVE 在客户區域上面
TVHT_BELOW 在客户區域下面
TVHT_NOWHERE 在客户區域中並在最後一項下面
TVHT_ONITEM 在與樹項關聯的位圖或標籤內
TVHT_ONITEMBUTTON 在與樹項關聯的按鈕上
TVHT_ONITEMICON 在與樹項關聯的位圖上
TVHT_ONITEMINDENT 在與樹項關聯的聯線上
TVHT_ONITEMLABEL 在與樹項關聯的標籤上
TVHT_ONITEMRIGHT 在樹項的右側區域中
TVHT_ONITEMSTATEICON 在用户定義的狀態圖標上
TVHT_TOLEFT 在客户區域的左側
TVHT_TORIGHT 在客户區域的右側

CTreeCtrl應用示例

這裏仍以基於對話框演示實例來具體介紹樹控制及其和圖像列表相結構的應用技巧:
通過“FILE->NEW->PROJECTS->MFC AppWizard(EXE)”建立名為VCTREE的工程,在建立過程中選擇基於對話框(Dialog based)的應用;將對話框中的默認控件刪除,並將所有對話框屬性中的Language域設置為Chinese(P.R.C.),以使應用程序支持中文;建立兩個圖標IDI_PM和IDI_CJ,用來表示圖標的選中和非選中狀態,對於每個圖標都應建立32X32和16X16兩種大小,以保證程序的需要;在對話框窗口中添加樹控制對象(TREE CONTROL),並設置五個按鈕“增加|刪除|查看|排序|關閉”,其對應標識分別如下:
控制名稱 標題名稱 標識符號
樹控制 IDC_TREECTRL
按鈕 增 加 IDC_ADD
刪 除 IDC_DEL
查 看 IDC_VIEW
排 序 IDC_SORT
關 閉 IDOK
選中樹控制控件,選擇“VIEW->ClassWizard->Member Variables。??DC_TREECTRL 引入成員變量,其變量類型為:
變量名 種類 變量類型
m_TreeCtrl Control CTreeCtrl
同時利用“MESSAGES MAP”為各命令按鈕增加控制功能函數。
然後在代碼文件VCTREEDlg.CPP中分別加入如下控制代碼:
(1)在文件開始處增加圖像列表定義
CImageList Cil1,Cil2;//大小圖標像列表
(2)在初始化文件開始處增加代碼
BOOL CVCTREEDlg::OnInitDialog()
{ CDialog::OnInitDialog();
.....//原來其它代碼
// TODO: Add extra initialization here
// 此處開始增加代碼
CVCTREEApp *pApp=(CVCTREEApp *)AfxGetApp();//創建圖象列表
Cil1.Create(16,16,ILC_COLOR,2,2);
Cil1.Add(pApp->LoadIcon(IDI_PM));
Cil1.Add(pApp->LoadIcon(IDI_CJ));
m_TreeCtrl.SetImageList(&Cil1,TVSIL_NORMAL); //設置圖象列表
DWORD dwStyles=GetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE);//獲取樹控制原風格
dwStyles|=TVS_EDITLABELS|TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT;
SetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE,dwStyles);//設置風格
char * CJ[4]={"玉溪捲煙廠","雲南捲煙廠","瀋陽捲煙廠","成都捲煙廠"};//根數據名稱
char * PM[4][5]={
{"紅梅一","紅梅二","紅梅三","紅梅四","紅梅五"},//產品數據項
{"白梅一","白梅二","白梅三","白梅四","白梅五"},
{"綠梅一","綠梅二","綠梅三","綠梅四","綠梅五"},
{"青梅一","青梅二","青梅三","青梅四","青梅五"}};
int i,j;
HTREEITEM hRoot,hCur;//樹控制項目句柄
TV_INSERTSTRUCT TCItem;//插入數據項數據結構
TCItem.hParent=TVI_ROOT;//增加根項
TCItem.hInsertAfter=TVI_LAST;//在最後項之後
TCItem.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//設屏蔽
TCItem.item.pszText="數據選擇";
TCItem.item.lParam=0;//序號
TCItem.item.iImage=0;//正常圖標
TCItem.item.iSelectedImage=1;//選中時圖標
hRoot=m_TreeCtrl.InsertItem(&TCItem);//返回根項句柄
for(i=0;i<4;i++){//增加各廠家
TCItem.hParent=hRoot;
TCItem.item.pszText=CJ[i];
TCItem.item.lParam=(i+1)*10;//子項序號
hCur=m_TreeCtrl.InsertItem(&TCItem);
for(j=0;j<5;j++){//增加各產品
TCItem.hParent=hCur;
TCItem.item.pszText=PM[i][j];
TCItem.item.lParam=(i+1)*10+(j+1);//子項序號
m_TreeCtrl.InsertItem(&TCItem);
}
m_TreeCtrl.Expand(hCur,TVE_EXPAND);//展開樹
}
m_TreeCtrl.Expand(hRoot,TVE_EXPAND);//展開上一級樹
return TRUE; // return TRUE unless you set the focus to a control
}
增加樹項功能的實現
在增加樹項功能時,除了需要定義和設置插入樹項的數據結構之外,還需要注意的是新增樹項的名稱初始時均為“新增數據”,增加後允許用户給數據項設置自定義名稱。在編程時應特別注意m_TreeCtrl.EditLabel(hInsert);後面不能跟任何其它程序命令,否則這條編輯指令無效。
void CVCTREEDlg::OnAdd()
{ //增加子項功能函數
HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選擇項句柄
if(hSel==NULL) return;//無任何選項則返回
static int nAddNo=100;//編號大於100為新增數據
TV_INSERTSTRUCT TCItem;//定義插入項數據結構
TCItem.hParent=hSel; //設置父項句柄
TCItem.hInsertAfter=TVI_LAST;//在最後增加
TCItem.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//設屏蔽
TCItem.item.pszText="新增數據";
TCItem.item.lParam=nAddNo++;//索引號增加
TCItem.item.iImage=0;//正常圖標
TCItem.item.iSelectedImage=1;//選中時圖標
HTREEITEM hInsert=m_TreeCtrl.InsertItem(&TCItem);//增加
m_TreeCtrl.Expand(hSel,TVE_EXPAND);
m_TreeCtrl.EditLabel(hInsert);//修改增加的數據
}
刪除樹項功能的實現
在實現刪除功能時,應對存在子項的樹項進行提示,以警告用户是否連同其子項一起刪除。
void CVCTREEDlg::OnDel()
{ //刪除子項功能函數
HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項句柄;
if(hSel==NULL) return;//無任何選項則返回
if(m_TreeCtrl.ItemHasChildren(hSel))//判斷是否有子項
if(MessageBox("廠家下存在品名,一同刪除?","警告",MB_YESNO)==IDNO) return;
m_TreeCtrl.DeleteItem(hSel);
}

CTreeCtrl項目用法

CTreeCtrl信息處理

BOOL CTreeCtrl::GetItem(TV_ITEM* pItem);BOOL CTreeCtrl::SetItem(TV_ITEM* pItem);BOOL CTreeCtrl::SetItem(HTREEITEM hItem,UINTnMask,LPCTSTR lpszItem,int Image,int nSelectedImage,UINT nState,UINT nStateMask,LPARAME lParam);

CTreeCtrl狀態處理

UINT CTreeCtrl::GetItemState(HTREEITEM hItem,UINT sStateMask)const;BOOL CTree Ctrl::SetItemState(HTREEITEM hItem,UINT nState,UINT nStateMask);

CTreeCtrl圖形處理

BOOL CTreeCtrl::GetItemImage(HTREEITEM hItem,int& nImage,int& nSelectedImage)const;BOOL CTreeCtrl::SetItemImage(HTREEITEM hItem,int nImage,int nSelectedImage);

CTreeCtrl文本處理

CString CTreeCtrl::GetItemText(HTREEITEM,hItem)const;BOOL CTreeCtrl::SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);

CTreeCtrl查詢項目

查詢項目個數UINT CTreeCtrl::GetCount();
查詢父項目句柄HTREEITEM CTreeCtrl::GetParentItem(HTREEITEM hItem);
查詢是否有子項BOOL CTreeCtrl::ItemHasChildren(HTREEITEM hItem);
取得首子項的句柄HTREEITEM CTreeCtrl::GetChildItem(HTREEITEM hItem);
查詢前後的兄弟項HTREEITEM CTreeCtrl::GetPrevSiblingItem(HTREEITEM hItem);HTREEITEM CTreeCtrl::GetNextSiblingItem(HTREEITEM hItem);

CTreeCtrl取得句柄

HTREEITEM CTreeCtrl::GetSelectedItem();
HTREEITEM CTreeCtrl::GetRootItem();
HTREEITEM hItem=GetRootItem(); //獲取根結點,可能會有多個根結點
ItemHasChildren(hParent) //判斷結點是否有子結點
hItem=GetChildItem(hParent); //獲取第一個子結點
hItem=GetNextSiblingItem(hItem)); //獲取下一個兄弟結點結點
Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);//展開/疊起結點
Select(hItem,TVGN_FIRSTVISIBLE); //設置選中結點
CString str=GetItemText(hChild); //獲取結點字符串信息
HTREEITEM hCurrSel = GetSelectedItem(); //獲取當前選中結點
SelectItem(hNewSel);
HTREEITEM hNewSel = HitTest(pt, &nFlags); //判斷座標是否在當前結點範圍內
HTREEITEM hItem=InsertItem(dlg.m_strItemText,hItemParent); //插入結點