基本介紹
- 中文名:樹控制項
- 外文名: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訊息
控制項屬性
樹控制項屬性類包括取得樹控制項中項數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等。
操作方法
樹控制項的操作方法包括插入一個樹項InsertItem、刪除一個樹項DeleteItem、刪除所有樹項DeleteAllItems、展開或合攏樹項的子項Expand、選中特定樹項SelectItem、選擇一個樹項作為第一個可視樹項SelectSetFirstVisible、編輯一個可視的樹項EditLabel和排序給定父樹項的子樹項SortChildren等。
數據結構
在使用樹控制項時需要了解兩個個非常重要的數據結構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 在客戶區域的右側
套用示例
這裡仍以基於對話框演示實例來具體介紹樹控制及其和圖像列表相結構的套用技巧:
通過“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);
}
項目用法
信息處理
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);
狀態處理
UINT CTreeCtrl::GetItemState(HTREEITEM hItem,UINT sStateMask)const;BOOL CTree Ctrl::SetItemState(HTREEITEM hItem,UINT nState,UINT nStateMask);
圖形處理
BOOL CTreeCtrl::GetItemImage(HTREEITEM hItem,int& nImage,int& nSelectedImage)const;BOOL CTreeCtrl::SetItemImage(HTREEITEM hItem,int nImage,int nSelectedImage);
文本處理
CString CTreeCtrl::GetItemText(HTREEITEM,hItem)const;BOOL CTreeCtrl::SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
查詢項目
查詢項目個數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);
取得句柄
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); //插入結點