分享

在Visual FoxPro中使用TreeView控件|TreeView 控件 VFP|时...

 昵称728549 2010-01-31
在Visual FoxPro中使用TreeView控件 


如果用户在设计程序时,需要用一种树形结构生动形象地显示具有不同层次的数据,那么TreeView控件将是最合适的选择。TreeView控件可以将用户选定的数据,也可以是从数据库中检索出来的数据,供用户自由的选择、展开或折迭收起。TreeView控件主要用以显示层次数据之间的关系。TreeView控件的特点包括以下几个方面: 


1、将相互间有联系的数据用图形与文字方式以树形描绘,以树形节点(Node对象)的形式展开或收起数据; 

2、每一个节点可以用图标和文本标签来描述; 
3、标签可以设置为是否允许修改的属性; 
4、对层次深度和节点数目无限制,只受系统资源的限制。 
另外,使用TreeView控件对管理信息量很大的数据来说,是一个很好的方式,因为用户能从中简单快速的选择到所需要的数据。Windows资源管理器就是TreeView控件、ImageList控件与ListView控件配合应用的一个例子。 
TreeView控件是Microsoft Visual Studio 中的一个控件,它是Mscomctl.ocx文件中的一组ActiveX控件的一部分。当安装了Visual FoxPro或Visual Basic后就可以在Windows的System目录中找到这个文件。为了在发布的应用程序中使用TreeView控件,必须将Mscomctl.ocx文件与应用程序一起做成安装盘发布。这个控件在Visual FoxPro 5.0中的版本是5.0,但是该控件的5.0版本不支持6.0版本的一些属性、方法和事件,所以要尽量使用6.0版本。如果没有Visual FoxPro 6.0也可以,只要找到Mscomctl.ocx这个文件并将其注册,就可以在Visual FoxPro 5.0中使用该控件的6.0版本。 
一个TreeView控件由若干Node对象组成,一个Node对象就是一个节点。一个TreeView控件只能有一个根节点(Root)。一个节点有若干子节点(Child),但必须有(除根节点以外)也只能有一个父节点(Parent)。创建TreeView控件之后,可以通过设置属性与调用方法操作各Node对象,包括添加、删除等。可以编程展开与折迭Node对象显示或隐藏子节点。 
在FoxPro主菜单的“工具”菜单的“选项”中“控件页框”,将“ActiveX控件”的“Microsoft TreeView Control,Version 6.0”选定,然后单击确定,即可将TreeView控件加入“表单控件工具栏”。单击表单控件工具栏的查看类按钮,弹出一个菜单,单击其中的“ActiveX控件”,即可在“表单控件工具栏”看到TreeView控件。将ImageList控件加入“表单控件工具栏”的方法与TreeView控件的方法一样。 
TreeView的外观只要看一下Windows资源管理器就很清楚了。要使用TreeView控件与其他普通控件一样,TreeView控件也是由属性、方法和事件控制的(以下假设表单加入的TreeView控件的Name属性是Tree)。设计时在控件上单击鼠标右键会弹出一个快捷菜单,单击“TreeCtrl Properties”就会出现一个标题为“TreeCtrl属性”的窗口,在这个窗口中可以设置控件的一些属性。但这里有一个“Bug”,如果在这里设置与ImageList控件的关联存不上盘,当时好象存上了,再次打开还是老样子。在后面Image属性的介绍中再详细说明任何解决这个问题。 
一、Node对象的属性 
在控件上单击右键,单击弹出式菜单的最后一项即可修改属性。 
1、Key(键值):一个节点的键值必须是唯一的字符型的值,控件用键值来区分节点,如果某两个节点的键值相同将会出错。键值可以由字母、下划线、空格和数字等可打印字符组成,但不能是纯数字的字符串,否则会出错。如用于显示磁盘目录,可以用路径作为键值。ThisForm.Tree.SelectedItem.Key或ThisForm.Tree.Nodes.Item(Node.Index).Key返回控件当前选定的节点的键值。 
2、Parent(父节点):一个节点只能有一个父节点,根节点没有父节点。ThisForm.Tree.SelectedItem.Parent.Key返回控件当前选定的节点的父节点的键值。如果当前选定的节点没有父节点,则这行代码就会出错。可用ThisForm.Tree.SelectdeItem.Parent是否为空值(Isnull)或ThisForm.Tree.SelectedItem.Index是否等于1判断该节点是否有父节点。 
3、Child(子节点):ThisForm.Tree.SelectedItem.Child.Key返回TreeView控件中当前选定的节点的第一个子节点的键值,如果该节点无子节点,该行代码会出错。可以使用下面这个属性看一下它有没有子节点。 
4、Children(子节点数目):ThisForm.Tree.SelectedItem.Children返回TreeView控件中当前选定的节点的子节点的数目。 
5、Text(节点标签):该属性返回用户所看到的节点的标签,不同节点的标签允许相同,也可以是空字符串。 
6、LabelEdit:该属性为0时双击标签,即可编辑标签。等于1时不可编辑。编辑标签时会触发AfterLabelEdit和BeforeLabelEdit事件。 
7、Singlesel:该属性为Ture时,被选定的节点如果有子节点将自动展开显示子节点。 
8、Sorted:当该属性为Ture时,节点按字母顺序排列。 
9、Expanded:当该属性为Ture时,表明该节点是展开的。 
10、Next:返回TreeView控件中同为Node节点的父节点的子节点的下一个兄弟节点的对象。 
11、Previous:返回TreeView控件中同为Node节点的父节点的子节点的前一个兄弟节点的对象。 
12、Style:返回或设置图形类型(图标、文本、+/-号、直线)以及出现在TreeView控件中每一Node对象上的文本类型。 
设置值 说明 
0 仅为文本 
1 图标和文本 
2 +/-和文本 
3 +/-、图标和文本 
4 直线和文本 
5 直线、图标和文本 
6 直线、+/-和文本 
7 (默认)图标、直线、+/-和文本 
 
13、Count: Nodes集合中的节点总数。该属性是Nodes集合的属性。 
14、Index:增加一个Node对象时就给其分配了索引值,保存在该Node对象的Index属性中。新成员的该属性值也是Nodes集合的Count属性值。 
15、Image:对应节点的图标键值。TreeView控件中的图标是另外一个控件ImageList提供的,在这个控件中为每一个图标指定一个唯一的键值,要改变节点的图标只要改变这个属性就可以了。在Visual FoxPro中TreeView控件有一个Bug,在设计时无法与ImageList相关联(在VB中没有此现象),这个问题可以解决,在表单的Init事件中加入下面三行就可以解决这个Bug(假定加入的ImageLiat控件Name属性为Images)。 
This.Tree.ImageList = This.Images 
二、方法 
1、Add:用于向TreeView控件加入节点 
语法:Object.Add (Relative,Relationship, Key, Text, Image, Selectedimage) 
①Object:对象名称,本例为ThisForm.Tree; 
②Relative:可选参数。已存在的Node对象的索引或键值。加入根节点时省略,加入子节点时是父节点的键值。 
③Relationship:可选参数。指定Node对象的相对位置关系。 
relationship值的设置如下: 
常量 值 描述 
TvwFirst 0 第一个。该Node节点放在relative命名的所有同级节点的前面 
TvwLast 1 最后一个。该Node节点放在relative命名的所有同级节点的最后。后续增加的节点可以在该节点之后 
TvwNext 2 (缺省)下一个。该Node节点放置在relative命名的节点之后 
TvwPrevious 3 前一个。该Node节点放置在relative命名的节点之前 
TvwChild 4 子节点。该Node节点是relative命名节点的子节点 
 
④Key:Node对象的键值。必须是字符串。 
⑤Text:Node对象的标签。必须是字符串。 
⑥Image:可选参数。与ImageList控件关联的图像索引或键值,也就是标签前面的图标。 
⑦Selectedimage:可选参数。当Node对象选中时,所显示的与ImageList控件关联的图像索引或键值。比如:节点未选中时显示关闭的文件夹图标,选中时显示打开的文件夹图标。 
2、Remove:从Node集合(Nodes)中删除一个节点。该节点的子节点将被一同删除(如果有的话)。 
语法:Object.Nodes.Remove(Key) 
①Object:对象名称,本例为ThisForm.Tree。 
②Key:Node对象的键值。 
3、Nodes( ):用Node对象的索引返回对象的引用。 
语法:Object.Nodes(Index) 
①Object:对象名称,本例为ThisForm.Tree。 
②Index:增加一个Node对象时给其分配的索引值。第一个加入的节点Index为1,第二个为2,依次类推。 
4、Nodes( ):用Node对象的键值返回对象的引用。 
语法:Object.Nodes(Key) 
①Object:对象名称,本例为ThisForm.Tree。 
②Key: Node对象的键值。 
三、事件 
1、BeforeLabelEdit:在试图编辑当前选中的Node对象标签时该事件发生。在LabelEdit=1时该事件失效。 
2、AfterLabelEdit:在编辑当前选中的Node对象标签后事件发生。在LabelEdit=1时该事件失效。 
3、Collapse:将已展开的节点折叠时事件发生。该事件发生在标准的Click事件之前。该事件返回被折叠的Node对象的引用。触发Collapse事件有三种方法: 
①设置Node对象的Expanded属性为False.; 
②双击展开的Node对象; 
③TreeView控件的Style属性为2、3、6或7时,单击“-”图象。 
4、Expand:在控件有子节点的Node对象扩展开时事件发生。该事件发生在标准的Click事件之前。该事件返回被展开的Node对象的引用。触发Expanded事件有三种方法: 
①设置Node对象的Expanded属性为True.; 
②双击带有子节点的Node对象; 
③TreeView控件的Style属性为2、3、6或7时,单击“+”图象。 
5、NodeClick:单击Node对象时该事件发生。该事件发生在标准的Click事件之前。在单击节点对象之外的控件任何部位,标准的Click事件发生。 
四、举例 
1、用表中数据增加节点。该表有_Parent(父节点键值),_Key(本节点键值),Text(节点文本),3个字段。 
select LS 
SCAN 
IF ALLTRIM(parent) = "0" 
Node = this.nodes.add(,1,ALLTRIM(LS.key),ALLTRIM(LS.Text),,) 
*加入根节点 
ELSE 
Node =this.nodes.add(ALLTRIM(LS.parent),4,ALLTRIM(LS.key),ALLTRIM(LS.Text),,) 
ENDIF 
ENDSCAN 
2、将所有节点信息存入一个临时表。该例将控件每一个节点的键值(_key)、标签(T_text)和父节点键值(_parent)存入临时表:LS。 
O=ThisForm.Tree  
*为了减少代码数量,建立一个对象变量来代替很长的对象名称。 
Create Cursor LS (_key c(10),T_text n(40),_parent c(10)) *创建临时表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) 
Endfor 
3、获取一个节点的所有父节点与子节点,并将其存入一个临时表LS1。临时表LS1存入所有节点的父节点键值(_parent)、本节点键值(_key)和本节点标签(T_text)。LS2用来模拟堆栈。 
O=ThisForm.Tree1 *建立对象变量既可以减少代码输入又可增加可读性只是速度稍慢 
Create Cursor LS1 (_parent c(10),_key c(10),T_text c(60)) 
Create Cursor LS2 (_index n(10)) 
Select LS2 
node_index=o.SelectedItem.Index *Tree1当前选定的节点索引值 
*下面代码获取该节点的父节点 
Do while .t. 
Insert Into Ls2 Value(o.Nodes(node_index).Index)  
If o.Nodes(node_index).Parent.Index=1 
Exit 
Endif 
node_index=o.Nodes(node_index).Parent.Index 
Enddo 
*由于上面代码获取的父节点排在子节点的后面,下面这个循环把顺序倒过来,使辈分高的节点排在前面。 
Do while .t. 
Go Bottom 
node_index=LS2._index 
If node_index=0 
Exit 
Endif 
Insert Into LS1 Value(o.Nodes(node_index).Parent.Key,; 
o.Nodes(node_index).Key,; 
o.Nodes(node_index).Text) 
Delete 
Enddo 
 
Select LS2 
child_number=o.SelectedItem.Children 
If Child_number>0 
node_index=o.SelectedItem.Index 
Do while node_index#0 
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) 
For i=2 to child_number 
node_index=LS2._index 
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) 
Endfor 
Select LS2 
Go Bottom 
Do while .t. 
node_index=LS2._index 
If node_index=0 
Exit 
Endif 
child_number=o.Nodes(node_index).Children 
If child_number=0 
Delete 
Go Bottom 
Loop 
Else 
Delete 
Exit 
Endif 
Enddo 
Go Bottom 
Enddo 
Endif 
Select Ls2 
Use 
五、其它: 
1、TreeView控件缺少一个检测节点是否存在的函数(不知道是不是我没有发现),当向一个控件加入一个节点时,如果键值重复就会出错。有一个办法“解决”问题,我暂且称之为“赖皮”算法,就是用On Error Lerror=.T.忽略所有错误,之后再用On Error 解除就会相安无事。见下例。如果没有第一行,当检测的节点不存在时,就会有错误窗口弹出。 
On Error Lerror=.T. 
If Isnull(Thisform.Tree.Nodes(Key)) 
On Error 
Return(.f.) 
Else 
On Error 
Return(.T.) 
Endif 
2、最后简要介绍ImagesList控件的使用方法。 
ImageList控件与TreeView控件都在文件Mscomctl.ocx中。在表单运行时该控件不可见,它的任务就是向其他控件提供图标。设计时在控件上单击鼠标右键,会弹出一个快捷菜单,单击“ImageListCtrl Properties”就会出现一个标题为“ImageListCtrl 属性”的窗口,在这个窗口中可以设置控件的属性。在这里先设置图标的大小,加入图标后大小就无法改变了。加入图标并指定图标的索引或键值后,就可以由其他控件随意调用图标了。5.0版的ImageList控件只能加入图标,6.0版的可以加入图片(当然不能太大),所以尽可能使用高版本。 

标签: TreeView 控件 VFP

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多