如果用戶在設(shè)計(jì)程序時(shí),,需要用一種樹形結(jié)構(gòu)生動(dòng)形象地顯示具有不同層次的數(shù)據(jù),那么TreeView控件將是最合適的選擇,。TreeView控件可以將用戶選定的數(shù)據(jù),,也可以是從數(shù)據(jù)庫中檢索出來的數(shù)據(jù),供用戶自由的選擇,、展開或折迭收起,。TreeView控件主要用以顯示層次數(shù)據(jù)之間的關(guān)系。TreeView控件的特點(diǎn)包括以下幾個(gè)方面: |
1,、將相互間有聯(lián)系的數(shù)據(jù)用圖形與文字方式以樹形描繪,,以樹形節(jié)點(diǎn)(Node對(duì)象)的形式展開或收起數(shù)據(jù); |
2,、每一個(gè)節(jié)點(diǎn)可以用圖標(biāo)和文本標(biāo)簽來描述,; |
3、標(biāo)簽可以設(shè)置為是否允許修改的屬性,; |
4,、對(duì)層次深度和節(jié)點(diǎn)數(shù)目無限制,只受系統(tǒng)資源的限制,。 |
另外,,使用TreeView控件對(duì)管理信息量很大的數(shù)據(jù)來說,是一個(gè)很好的方式,,因?yàn)橛脩裟軓闹泻?jiǎn)單快速的選擇到所需要的數(shù)據(jù),。Windows資源管理器就是TreeView控件、ImageList控件與ListView控件配合應(yīng)用的一個(gè)例子,。 |
TreeView控件是Microsoft Visual Studio 中的一個(gè)控件,,它是Mscomctl.ocx文件中的一組ActiveX控件的一部分,。當(dāng)安裝了Visual FoxPro或Visual Basic后就可以在Windows的System目錄中找到這個(gè)文件。為了在發(fā)布的應(yīng)用程序中使用TreeView控件,,必須將Mscomctl.ocx文件與應(yīng)用程序一起做成安裝盤發(fā)布,。這個(gè)控件在Visual FoxPro 5.0中的版本是5.0,但是該控件的5.0版本不支持6.0版本的一些屬性,、方法和事件,,所以要盡量使用6.0版本。如果沒有Visual FoxPro 6.0也可以,,只要找到Mscomctl.ocx這個(gè)文件并將其注冊(cè),,就可以在Visual FoxPro 5.0中使用該控件的6.0版本。 |
一個(gè)TreeView控件由若干Node對(duì)象組成,,一個(gè)Node對(duì)象就是一個(gè)節(jié)點(diǎn),。一個(gè)TreeView控件只能有一個(gè)根節(jié)點(diǎn)(Root)。一個(gè)節(jié)點(diǎn)有若干子節(jié)點(diǎn)(Child),,但必須有(除根節(jié)點(diǎn)以外)也只能有一個(gè)父節(jié)點(diǎn)(Parent),。創(chuàng)建TreeView控件之后,可以通過設(shè)置屬性與調(diào)用方法操作各Node對(duì)象,,包括添加,、刪除等??梢跃幊陶归_與折迭Node對(duì)象顯示或隱藏子節(jié)點(diǎn),。 |
在FoxPro主菜單的“工具”菜單的“選項(xiàng)”中“控件頁框”,將“ActiveX控件”的“Microsoft TreeView Control,Version 6.0”選定,,然后單擊確定,,即可將TreeView控件加入“表單控件工具欄”。單擊表單控件工具欄的查看類按鈕,,彈出一個(gè)菜單,,單擊其中的“ActiveX控件”,即可在“表單控件工具欄”看到TreeView控件,。將ImageList控件加入“表單控件工具欄”的方法與TreeView控件的方法一樣,。 |
TreeView的外觀只要看一下Windows資源管理器就很清楚了。要使用TreeView控件與其他普通控件一樣,,TreeView控件也是由屬性,、方法和事件控制的(以下假設(shè)表單加入的TreeView控件的Name屬性是Tree)。設(shè)計(jì)時(shí)在控件上單擊鼠標(biāo)右鍵會(huì)彈出一個(gè)快捷菜單,,單擊“TreeCtrl Properties”就會(huì)出現(xiàn)一個(gè)標(biāo)題為“TreeCtrl屬性”的窗口,,在這個(gè)窗口中可以設(shè)置控件的一些屬性。但這里有一個(gè)“Bug”,,如果在這里設(shè)置與ImageList控件的關(guān)聯(lián)存不上盤,,當(dāng)時(shí)好象存上了,,再次打開還是老樣子。在后面Image屬性的介紹中再詳細(xì)說明任何解決這個(gè)問題,。 |
在控件上單擊右鍵,單擊彈出式菜單的最后一項(xiàng)即可修改屬性,。 |
1,、Key(鍵值):一個(gè)節(jié)點(diǎn)的鍵值必須是唯一的字符型的值,控件用鍵值來區(qū)分節(jié)點(diǎn),,如果某兩個(gè)節(jié)點(diǎn)的鍵值相同將會(huì)出錯(cuò)。鍵值可以由字母,、下劃線,、空格和數(shù)字等可打印字符組成,但不能是純數(shù)字的字符串,,否則會(huì)出錯(cuò),。如用于顯示磁盤目錄,可以用路徑作為鍵值,。
ThisForm.Tree.SelectedItem.Key
或
ThisForm.Tree.Nodes.Item(Node.Index).Key 返回控件當(dāng)前選定的節(jié)點(diǎn)的鍵值,。
|
2、Parent(父節(jié)點(diǎn)):一個(gè)節(jié)點(diǎn)只能有一個(gè)父節(jié)點(diǎn),,根節(jié)點(diǎn)沒有父節(jié)點(diǎn),。
ThisForm.Tree.SelectedItem.Parent.Key
返回控件當(dāng)前選定的節(jié)點(diǎn)的父節(jié)點(diǎn)的鍵值。如果當(dāng)前選定的節(jié)點(diǎn)沒有父節(jié)點(diǎn),,則這行代碼就會(huì)出錯(cuò),。
可用ThisForm.Tree.SelectdeItem.Parent是否為空值(Isnull)或ThisForm.Tree.SelectedItem.Index是否等于1判斷該節(jié)點(diǎn)是否有父節(jié)點(diǎn)。
|
3,、Child(子節(jié)點(diǎn)):
ThisForm.Tree.SelectedItem.Child.Key返回TreeView控件中當(dāng)前選定的節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)的鍵值,,如果該節(jié)點(diǎn)無子節(jié)點(diǎn),該行代碼會(huì)出錯(cuò),??梢允褂孟旅孢@個(gè)屬性看一下它有沒有子節(jié)點(diǎn)。
|
4,、Children(子節(jié)點(diǎn)數(shù)目):ThisForm.Tree.SelectedItem.Children返回TreeView控件中當(dāng)前選定的節(jié)點(diǎn)的子節(jié)點(diǎn)的數(shù)目,。 |
5、Text(節(jié)點(diǎn)標(biāo)簽):該屬性返回用戶所看到的節(jié)點(diǎn)的標(biāo)簽,,不同節(jié)點(diǎn)的標(biāo)簽允許相同,,也可以是空字符串。 |
6,、LabelEdit:該屬性為0時(shí)雙擊標(biāo)簽,,即可編輯標(biāo)簽,。等于1時(shí)不可編輯。編輯標(biāo)簽時(shí)會(huì)觸發(fā)AfterLabelEdit和BeforeLabelEdit事件,。 |
7,、Singlesel:該屬性為Ture時(shí),被選定的節(jié)點(diǎn)如果有子節(jié)點(diǎn)將自動(dòng)展開顯示子節(jié)點(diǎn),。 |
8,、Sorted:當(dāng)該屬性為Ture時(shí),節(jié)點(diǎn)按字母順序排列,。 |
9,、Expanded:當(dāng)該屬性為Ture時(shí),表明該節(jié)點(diǎn)是展開的,。 |
10,、Next:返回TreeView控件中同為Node節(jié)點(diǎn)的父節(jié)點(diǎn)的子節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)的對(duì)象。 |
11,、Previous:返回TreeView控件中同為Node節(jié)點(diǎn)的父節(jié)點(diǎn)的子節(jié)點(diǎn)的前一個(gè)兄弟節(jié)點(diǎn)的對(duì)象,。 |
12、Style:返回或設(shè)置圖形類型(圖標(biāo),、文本,、+/-號(hào)、直線)以及出現(xiàn)在TreeView控件中每一Node對(duì)象上的文本類型,。 |
設(shè)置值 |
說明 |
0 |
僅為文本 |
1 |
圖標(biāo)和文本 |
2 |
+/-和文本 |
3 |
+/-,、圖標(biāo)和文本 |
4 |
直線和文本 |
5 |
直線、圖標(biāo)和文本 |
6 |
直線,、+/-和文本 |
7 |
(默認(rèn))圖標(biāo),、直線、+/-和文本 |
|
13,、Count: Nodes集合中的節(jié)點(diǎn)總數(shù),。該屬性是Nodes集合的屬性。 |
14,、Index:增加一個(gè)Node對(duì)象時(shí)就給其分配了索引值,,保存在該Node對(duì)象的Index屬性中。新成員的該屬性值也是Nodes集合的Count屬性值,。 |
15,、Image:對(duì)應(yīng)節(jié)點(diǎn)的圖標(biāo)鍵值。TreeView控件中的圖標(biāo)是另外一個(gè)控件ImageList提供的,,在這個(gè)控件中為每一個(gè)圖標(biāo)指定一個(gè)唯一的鍵值,,要改變節(jié)點(diǎn)的圖標(biāo)只要改變這個(gè)屬性就可以了。在Visual FoxPro中TreeView控件有一個(gè)Bug,,在設(shè)計(jì)時(shí)無法與ImageList相關(guān)聯(lián)(在VB中沒有此現(xiàn)象),,這個(gè)問題可以解決,,在表單的Init事件中加入下面三行就可以解決這個(gè)Bug(假定加入的ImageLiat控件Name屬性為Images)。 |
This.Tree.ImageList = This.Images |
1,、Add:用于向TreeView控件加入節(jié)點(diǎn) |
語法:Object.Add (Relative,Relationship, Key, Text, Image, Selectedimage) |
①Object:對(duì)象名稱,本例為ThisForm.Tree,; |
②Relative:可選參數(shù),。已存在的Node對(duì)象的索引或鍵值。加入根節(jié)點(diǎn)時(shí)省略,,加入子節(jié)點(diǎn)時(shí)是父節(jié)點(diǎn)的鍵值,。問題加入同級(jí)節(jié)點(diǎn)時(shí)可以省掉吧!?。,。?/span> |
③Relationship:可選參數(shù),。指定Node對(duì)象的相對(duì)位置關(guān)系。 |
常量 |
值 |
描述 |
TvwFirst |
0 |
第一個(gè),。該Node節(jié)點(diǎn)放在relative命名的所有同級(jí)節(jié)點(diǎn)的前面 |
TvwLast |
1 |
最后一個(gè),。該Node節(jié)點(diǎn)放在relative命名的所有同級(jí)節(jié)點(diǎn)的最后。后續(xù)增加的節(jié)點(diǎn)可以在該節(jié)點(diǎn)之后 |
TvwNext |
2 |
(缺?。┫乱粋€(gè),。該Node節(jié)點(diǎn)放置在relative命名的節(jié)點(diǎn)之后 |
TvwPrevious |
3 |
前一個(gè)。該Node節(jié)點(diǎn)放置在relative命名的節(jié)點(diǎn)之前 |
TvwChild |
4 |
子節(jié)點(diǎn),。該Node節(jié)點(diǎn)是relative命名節(jié)點(diǎn)的子節(jié)點(diǎn) |
|
④Key:Node對(duì)象的鍵值,。必須是字符串。 |
⑤Text:Node對(duì)象的標(biāo)簽,。必須是字符串,。 |
⑥Image:可選參數(shù)。與ImageList控件關(guān)聯(lián)的圖像索引或鍵值,,也就是標(biāo)簽前面的圖標(biāo),。 |
⑦Selectedimage:可選參數(shù)。當(dāng)Node對(duì)象選中時(shí),,所顯示的與ImageList控件關(guān)聯(lián)的圖像索引或鍵值,。比如:節(jié)點(diǎn)未選中時(shí)顯示關(guān)閉的文件夾圖標(biāo),選中時(shí)顯示打開的文件夾圖標(biāo),。 |
2,、Remove:從Node集合(Nodes)中刪除一個(gè)節(jié)點(diǎn)。該節(jié)點(diǎn)的子節(jié)點(diǎn)將被一同刪除(如果有的話),。 |
語法:Object.Nodes.Remove(Key) |
①Object:對(duì)象名稱,,本例為ThisForm.Tree,。 |
3,、Nodes( ):用Node對(duì)象的索引返回對(duì)象的引用,。 |
①Object:對(duì)象名稱,本例為ThisForm.Tree,。 |
②Index:增加一個(gè)Node對(duì)象時(shí)給其分配的索引值,。第一個(gè)加入的節(jié)點(diǎn)Index為1,第二個(gè)為2,,依次類推,。 |
4、Nodes( ):用Node對(duì)象的鍵值返回對(duì)象的引用,。 |
①Object:對(duì)象名稱,,本例為ThisForm.Tree。 |
1、BeforeLabelEdit:在試圖編輯當(dāng)前選中的Node對(duì)象標(biāo)簽時(shí)該事件發(fā)生,。在LabelEdit=1時(shí)該事件失效,。 |
2、AfterLabelEdit:在編輯當(dāng)前選中的Node對(duì)象標(biāo)簽后事件發(fā)生,。在LabelEdit=1時(shí)該事件失效,。 |
3、Collapse:將已展開的節(jié)點(diǎn)折疊時(shí)事件發(fā)生,。該事件發(fā)生在標(biāo)準(zhǔn)的Click事件之前,。該事件返回被折疊的Node對(duì)象的引用。觸發(fā)Collapse事件有三種方法: |
①設(shè)置Node對(duì)象的Expanded屬性為False.,; |
③TreeView控件的Style屬性為2、3,、6或7時(shí),,單擊“-”圖象。 |
4,、Expand:在控件有子節(jié)點(diǎn)的Node對(duì)象擴(kuò)展開時(shí)事件發(fā)生,。該事件發(fā)生在標(biāo)準(zhǔn)的Click事件之前。該事件返回被展開的Node對(duì)象的引用,。觸發(fā)Expanded事件有三種方法: |
①設(shè)置Node對(duì)象的Expanded屬性為True.,; |
②雙擊帶有子節(jié)點(diǎn)的Node對(duì)象; |
③TreeView控件的Style屬性為2、3,、6或7時(shí),,單擊“+”圖象。 |
5,、NodeClick:?jiǎn)螕鬘ode對(duì)象時(shí)該事件發(fā)生,。該事件發(fā)生在標(biāo)準(zhǔn)的Click事件之前。在單擊節(jié)點(diǎn)對(duì)象之外的控件任何部位,,標(biāo)準(zhǔn)的Click事件發(fā)生,。 |
1,、用表中數(shù)據(jù)增加節(jié)點(diǎn),。該表有_Parent(父節(jié)點(diǎn)鍵值),_Key(本節(jié)點(diǎn)鍵值),,Text(節(jié)點(diǎn)文本),,3個(gè)字段。 |
Node = this.nodes.add(,1,ALLTRIM(LS.key),ALLTRIM(LS.Text),,) |
Node =this.nodes.add(ALLTRIM(LS.parent),4,ALLTRIM(LS.key),ALLTRIM(LS.Text),,) |
2,、將所有節(jié)點(diǎn)信息存入一個(gè)臨時(shí)表,。該例將控件每一個(gè)節(jié)點(diǎn)的鍵值(_key)、標(biāo)簽(T_text)和父節(jié)點(diǎn)鍵值(_parent)存入臨時(shí)表:LS,。 |
*為了減少代碼數(shù)量,,建立一個(gè)對(duì)象變量來代替很長(zhǎng)的對(duì)象名稱。 |
Create Cursor LS (_key c(10),T_text n(40),_parent c(10)) *?jiǎng)?chuàng)建臨時(shí)表LS |
For I=1 to O.Nodes.count() |
Insert Into LS Value(O.Nodes(I).Key,O.Nodes(I).Text,O.Nodes(I)._parent.Key) |
3,、獲取一個(gè)節(jié)點(diǎn)的所有父節(jié)點(diǎn)與子節(jié)點(diǎn),并將其存入一個(gè)臨時(shí)表LS1,。臨時(shí)表LS1存入所有節(jié)點(diǎn)的父節(jié)點(diǎn)鍵值(_parent),、本節(jié)點(diǎn)鍵值(_key)和本節(jié)點(diǎn)標(biāo)簽(T_text)。LS2用來模擬堆棧,。 |
O=ThisForm.Tree1 *建立對(duì)象變量既可以減少代碼輸入又可增加可讀性只是速度稍慢 |
Create Cursor LS1 (_parent c(10),_key c(10),T_text c(60)) |
Create Cursor LS2 (_index n(10)) |
node_index=o.SelectedItem.Index *Tree1當(dāng)前選定的節(jié)點(diǎn)索引值 |
*下面代碼獲取該節(jié)點(diǎn)的父節(jié)點(diǎn) |
Insert Into Ls2 Value(o.Nodes(node_index).Index) |
If o.Nodes(node_index).Parent.Index=1 |
node_index=o.Nodes(node_index).Parent.Index |
*由于上面代碼獲取的父節(jié)點(diǎn)排在子節(jié)點(diǎn)的后面,,下面這個(gè)循環(huán)把順序倒過來,使輩分高的節(jié)點(diǎn)排在前面,。 |
Insert Into LS1 Value(o.Nodes(node_index).Parent.Key,; |
o.Nodes(node_index).Key,; |
o.Nodes(node_index).Text) |
child_number=o.SelectedItem.Children |
node_index=o.SelectedItem.Index |
Insert Into LS2 Value(o.Nodes(node_index).Child.Index) |
Insert Into Ls1 Value(o.Nodes(node_index).Key,; |
o.Nodes(node_index).Child.Key,; |
o.Nodes(node_index).Child.Text) |
Insert Into LS2 Value(o.Nodes(node_index).Next.Index) |
Insert Into LS1 Value(o.Nodes(node_index).Next.Parent.Key,; |
o.Nodes(node_index).Next.Key,; |
o.Nodes(node_index).Next.Text) |
child_number=o.Nodes(node_index).Children |
1、TreeView控件缺少一個(gè)檢測(cè)節(jié)點(diǎn)是否存在的函數(shù)(不知道是不是我沒有發(fā)現(xiàn)),,當(dāng)向一個(gè)控件加入一個(gè)節(jié)點(diǎn)時(shí),,如果鍵值重復(fù)就會(huì)出錯(cuò)。有一個(gè)辦法“解決”問題,,我暫且稱之為“賴皮”算法,,就是用On Error Lerror=.T.忽略所有錯(cuò)誤,之后再用On Error 解除就會(huì)相安無事,。見下例,。如果沒有第一行,,當(dāng)檢測(cè)的節(jié)點(diǎn)不存在時(shí),就會(huì)有錯(cuò)誤窗口彈出,。 |
If Isnull(Thisform.Tree.Nodes(Key)) |
2,、最后簡(jiǎn)要介紹ImagesList控件的使用方法。 |
ImageList控件與TreeView控件都在文件Mscomctl.ocx中,。在表單運(yùn)行時(shí)該控件不可見,,它的任務(wù)就是向其他控件提供圖標(biāo)。設(shè)計(jì)時(shí)在控件上單擊鼠標(biāo)右鍵,,會(huì)彈出一個(gè)快捷菜單,,單擊“ImageListCtrl Properties”就會(huì)出現(xiàn)一個(gè)標(biāo)題為“ImageListCtrl 屬性”的窗口,在這個(gè)窗口中可以設(shè)置控件的屬性,。在這里先設(shè)置圖標(biāo)的大小,,加入圖標(biāo)后大小就無法改變了。加入圖標(biāo)并指定圖標(biāo)的索引或鍵值后,,就可以由其他控件隨意調(diào)用圖標(biāo)了,。5.0版的ImageList控件只能加入圖標(biāo),6.0版的可以加入圖片(當(dāng)然不能太大),,所以盡可能使用高版本 |
|