CTreeView說明

(一)樹控制的主要功能

樹控制和視(Tree Control&View)主要用來顯示具有一定層次結構的數據項,如資源管理器中的磁盤目錄等,以供用戶在其中進行各種選擇。樹控制中的每個數據項包括數據項名稱的文本字符串和用於表示該數據項的圖像,每個數據項下面均可包含各種子項,整個結構就象目錄樹一樣。對於包含各種子項的數據項,可通過鼠標雙擊來展開或合攏,這可以通過控制樹的不同風格來實現樹控制的不同顯示形態。這些風格主要包括:

TVS_HASLINES表示用連線來連接父項和它下面的各個子項,這可以使樹的顯示層次結構更加清晰,但在無父項的各子項之間並沒有連線;

TVS_LINESATROOT表示在無父項的各子項即根下面的各子項之間存在連線;

TVS_HASBUTTONS表示在帶有子項的父項前面增加一個帶“+”或“-”的按鈕,這使得用戶也可以通過單擊這個小按鈕來實現子項的展開和合攏,當存在子項時,按鈕的初始狀態爲“+”,當子項被展開時,按小按鈕由“+”變爲“-”號,當子項合攏時,小按鈕由“-”變爲“+”號,這一風格同樣對於根項無效,如果需要可通過組合TVS_LINESATROOT風格來實現;

TVS_EDITLABELS表示允許讓用戶單擊具有輸入焦點的數據項來修改其名稱。

對於樹控制,MFC中也以兩種形式來封裝,即樹控制(CTREECTRL)和樹視(CTREEVIEW),來滿足用戶的不同需求,對於一般要求的用戶如在對話框中應用,使用樹控制比較方便,而對於具有較高要求的用戶,在使用樹視時還具有視窗口的各種方便特性,可以更好地滿足文檔/視結構的要求。當在窗口中使用樹視時,樹視會佔滿兩個窗口的客戶區域並自動隨窗口的框架結構的調整而調整,並能夠很好地處理諸如菜單、加速鍵和工具條中的各種命令消息。在使用樹視時只要利用其成員函數CtreeView取得其一個引用,就可以象樹控制一樣方便地應用:CtreeCtrl &treeCtrl = GetTreeCtrl()。

(二)樹控制的對象結構

1、樹控制的建立方法

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消息

2、樹控制的屬性類

樹控制屬性類包括取得樹控制中項數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等。

3、樹控制的操作方法

樹控制的操作方法包括插入一個樹項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


5、選中樹控制控件,選擇“VIEW->ClassWizard->Memory Variables。 骺刂艻DC_TREECTRL 引入成員變量,其變量類型爲:

變量名 種類 變量類型

m_TreeCtrl Control CTreeCtrl

同時利用“MESSAGES MAP”爲各命令按鈕增加控制功能函數。

6、然後在代碼文件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

}

(3)增加樹項功能的實現

在增加樹項功能時,除了需要定義和設置插入樹項的數據結構之外,還需要注意的是新增樹項的名稱初始時均爲“新增數據”,增加後允許用戶給數據項設置自定義名稱。在編程時應特別注意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);//修改增加的數據

}

(4)刪除樹項功能的實現

在實現刪除功能時,應對存在子項的樹項進行提示,以警告用戶是否連同其子項一起刪除。

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);

}

(5)排序功能的實現

排序功能是對所選中的樹項的所有子項按字符中順序進行排序,如果想要按照其它規則進行排序,應利用SortChildrenItemBC()函數進行自行開發排序程序,這個自行開發的函數與列表控制中實現的函數基本相同,可興趣的讀可以試驗。

void CVCTREEDlg::OnSort()

{ //排序子項功能函數

HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項句柄;

if(hSel==NULL) return;//無任何選項則返回

m_TreeCtrl.SortChildren(hSel);

}

(6)查看功能的實現

查看功能用來查看選中樹項的有關信息,函數中中顯示了樹項的文本名稱和標識號,可以將這兩個信息作爲查找關鍵字,來查看其它更詳細的信息。

void CVCTREEDlg::OnView()

{ //查看選中項功能函數

HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項句柄;

if(hSel==NULL) return;//無任何選項則返回

CString cText=m_TreeCtrl.GetItemText(hSel);//取得數據項名

LONG IDs=m_TreeCtrl.GetItemData(hSel);//取得數據項序號

char temp[100];

wsprintf(temp,"廠家:%s 編號:%05d",cText,IDs);

MessageBox(temp,"選擇信息");

}

(7)修改功能的實現

如果不進行其它處理,當修改樹項的文本名稱後,就會發現其未被修改,這是因爲程序中沒有對修改結果進行保存處理,這就要利用TV_DISPINFO結構和SetItemText函數對TVN_ENDLABELEDIT進行處理,這樣就可以正確地實現修改功能。

void CVCTREEDlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult)

{ TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;

// TODO: Add your control notification handler code here

if(pTVDispInfo->item.pszText==0) return;//用戶取消修改操作

m_TreeCtrl.SetItemText(pTVDispInfo->item.hItem,

pTVDispInfo->item.pszText);//設置新數據

*pResult = 0;

}

7、樹視的演練技巧

樹視的應用技巧在使用樹視時,其方法與樹控制基本相同,只不過樹視是在窗口中來實現的而樹控制是在對話框中實現,樹視的各種功能是通過菜單來實現的而樹控制是通過按鈕等方式來實現的,樹控制需要在對話框中創建樹控制控件而樹視直接佔據整個窗口,在設計過程中只要將按鈕和樹控制設計過程變爲菜單設計,並注意在功能函數是在類嚮導中是通過菜單命令來操作,同時在每個功能函數前面增加取得列表視引用的命令(CTreeCtrl& TreeCtrl = GetTreeCtrl()),而其餘數據結構和代碼均不需要修改,實現起來比較容易。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章