第十节常用控件
应用背景
VB程序爱好者常常不满足VB提供的标准控件,期望在程序中使用更高级的且能够体现职业化特点的第三方控件,这些控件使程序功能更加丰富、用户界面更专业、满足工程的真实需求。
树型控件TreeView,列表框控件ListView和表格控件FlexGrid是目前很多程序经常使用的控件,因此作为一个职业程序员,应该了解这些控件的使用方法和效果。图10-1为使用TreeView和ListView的注册表窗体图例,窗体左侧使用树型控件代表层次,右边使用列表控件显示左侧选中的内容。
图10-1注册表的树型结构和内容列表
知识要点
(1)TreeView控件
TreeView是最灵活的Windows控件之一,它以分层的形式显示数据,允许用户随意扩展或折叠节点。鉴于实际生活中许多事物有着层次关系,如计算机里的文件夹、人事组织关系、地区从属关系等,TreeView的应用也极其广泛。
在新建工程中,由于TreeView控件非标准控件,需要单击“工程/部件”,在控件列表中选中“Microsoft Windows command controls6.0(sp4)”,按下“确定”按钮返回主界面,则在左侧控件工具条中出现Treeview 控件选项。
TreeView的每个结点都为Node对象,这些结点的集合为Nodes,其有
基本属性和方法如下:
Count:返回所有Node的结点数
Add:增加结点方法,即
Add([父节点key],[关系],[结点key],[结点显示标题],[图像序号])
增加根结点
Set nodx = TreeView1.Nodes.Add(, , "huabei", "华北", 1)
增加上面根结点的子结点:
Set nodx = TreeView1.Nodes.Add("huabei", tvwChild, "beijing", "北京", 2)
其中[结点key],用于标志结点的唯一性,字符型变量;[节点显示标题]用于结点的显示,[图像序号]为显示该结点的图标在ImageList中的列表序号。
Remove(Index):删除序号为index的结点,如:Remove TreeView1.SelectedItem.Index '删除选定的节点
TreeView控件的属性
Sorted:用于给TreeView进行排序
ImageList:设置TreeView显示图标控件,如TreeView1. ImageList = ImageList1
LineStyle:TreeView结点之间显示的线形,如:TreeView1.LineStyle = tvwTreeLines
Style:TreeView击点显示的形式,如:TreeView1.Style = tvwTreelinesPictureText
Refresh:刷新方法,重新显示TreeView各个结点。
Clear:清除TreeView控件的所有Node结点。
下列代码,完成一个地区树型结构的加载:
Dim nodx As Node
TreeView1.ImageList = ImageList1
TreeView1.LineStyle = tvwTreeLines
TreeView1.Style = tvwTreelinesPictureText
Set nodx = TreeView1.Nodes.Add(, , "xibei", "西北", 1)
Set nodx = TreeView1.Nodes.Add("xibei", tvwChild, "xian", "西安", 2)
Set nodx = TreeView1.Nodes.Add("xibei", tvwChild, "yinchuan", "银川", 2)
Set nodx = TreeView1.Nodes.Add("xibei", tvwChild, "taiyuan", "太原", 2)
Set nodx = TreeView1.Nodes.Add(, , "xinan", "西南", 1)
Set nodx = TreeView1.Nodes.Add("xinan", tvwChild, "guiyang", "贵阳", 2)
Set nodx = TreeView1.Nodes.Add("xinan", tvwChild, "beihai", "北海", 2)
Set nodx = TreeView1.Nodes.Add("xinan", tvwChild, "nanning", "南宁", 2) TreeView1.Sorted = True
TreeView1.Refresh
(2)ListView控件
listview控件可有4种不同的视图显示方法,跟“资源管理器”里的“查看”方式相似:0大图标、1小图标、2列表、3报表式。使用哪种视图,可由该控件的view属性设置控制,其中“报表”视图很适合用来显示数据记录。
listview控件包括listItem对象和ColumnHeader对象。listItem 对象为显示的数据行;ColumnHeader对象为显示的列标题。
listItem对象有两部分,一部分是图标和简要描述的文本(第1列),另一部分是前者的子项文本信息(第2列,第3列......),而listItems 即是对listItem对象集合(所有行)的引用,因此listItems(1) 可以表示为第1行,listitems(1).text 返回第1行第1列的文本值,listitems(1).subItem(1) 返回第1行第2列的文本值。
ListView常用属性:
Checkboxes:设置为true时,每一行数据前将显示一复选框。
FullRowSelect:设置为true时可以整行地选择数据。
GridLines:设置为true时控件将显示网格线,只作用于“报表”视图
HotTracking:设置为true时,鼠标所在行将以高亮度显示。
LabelWrap:设置为true时,文本标签超出列宽时可换行。
SelectedItem:返回对所选ListItem对象的引用。
Sorted:当值为true时,列表按字母排序。
ListView常用方法:
Add方法:添加listItem对象到控件中。语法格式:
控件名.ListItems.add(index,key,text,icon,smallIcon)
FindItem方法:查找并返回对控件中listItem对象的引用。语法格式:控件名.FindItem(string,value,index,match)
ListView选定记录:
selectedItem.text 返回选定行第1列文本值
selectedItem.index 返回选定行的位置
listItems(x).subItems(y) 返回第x行,第y+1列文本值
listItems(x).checked=true 第x行复选框选定或返回值
ListView清除选定行:
listitems.remove(控件名.selectedItem.index)
所有行的总数:
listitems.count
例如下列代码完成一个ListView的记录加载过程:
Dim lst As ListItem
ListView1.ListItems.Clear
ListView1.Checkboxes = True
ListView1.FullRowSelect = True
ListView1.GridLines = True
ListView1.HotTracking = True
https://www.doczj.com/doc/e213684857.html,belWrap = True
ListView1.ColumnHeaderIcons = ImageList1
ListView1.SmallIcons = ImageList2
ListView1.Icons = ImageList1
ListView1.ColumnHeaders.Add , "h1", "区县名称", ListView1.Width / 4, 0, 1
ListView1.ColumnHeaders.Add , "h2", "电话", ListView1.Width / 4, 0, 2
ListView1.ColumnHeaders.Add , "h3", "地址", ListView1.Width / 4, 0, 3
ListView1.ColumnHeaders.Add , "h4", "联系人", ListView1.Width / 4, 0, 4
ListView1.ListItems.Add 1, "haidian", "海淀", 3, 3
ListView1.ListItems(1).SubItems(1) = 7876665
ListView1.ListItems(1).SubItems(2) = "海淀区学院南路68号"
ListView1.ListItems(1).SubItems(3) = "白先生"
ListView1.ListItems.Add 2, "shijingshan", "石景山", 3, 3 ListView1.ListItems.Add 3, "dongcheng", "东城区", 3, 3
ListView1.ListItems.Add 4, "xicheng", "西城区", 3, 3
ListView1.ListItems.Add 5, "shunyi", "顺义区", 3, 3
ListView1.ListItems.Add 6, "changping", "昌平区", 3, 3
ListView1.ListItems(6).SubItems(1) = 44332111
ListView1.ListItems(6).SubItems(2) = "昌平区大学城1号"
ListView1.ListItems(6).SubItems(3) = "刘先生"
ListView1.ListItems.Add 7, "fengtai", "丰台区", 3, 3
ListView1.ListItems.Add 8, "mentougou", "门头沟", 3, 3 (3)MSFlexgrid
Msflexgrid 控件是用表格式窗体显示信息的有用工具。利用该控件可以显示和操作数据表格,对包含字符串和图片的表格提供了灵活的排序、插入数据和格式编排功能。
常用属性:
TextMatrix(m,n):m代表行,n代表列,返回或设置当前行列的文本,例如将文本赋值给单元格:MsFlexGrid.TextMatrix(3,1)=”Hello”
Row,Col:代表所选单元列和行,例如选中行为5,列为4的单元:MsF lexGrid.Row=4;MsFlexGrid.Col=5。
CellPicture:代表所选单元,单元背景,在单元格中插入背景图形:S et MsFlexGrid.CellPicture=LoadPicture(“C:\temp\1.bmp”) CellFontBold:代表当前单元的字体,用粗体格式化当前选中单元:M sFlexGrid.CellFontBold=True
AllowBigSelection:设置网格样式
FillStyle :填充样式
RowSel:得到MSFlexGrid控件中当前选中的一行,如:msflexgrid1. Rowsel返回当前选中行。
ColSel: 得到MSFlexGrid控件中当前选中的一列,如:msflexgrid1. ColSel返回当前选中列。
Colwidth(Index):通过代码调节列宽度,例如:msflexgrid1.colwidt h(i)=4000
下列代码是对 MSFlexGrid初始化,仔细品读:
MSFlexGrid1.Cols = 6
MSFlexGrid1.Rows = 9
MSFlexGrid1.AllowBigSelection = True
MSFlexGrid1.FillStyle = flexFillRepeat
Dim i, j As Integer
MSFlexGrid1.Row = 0
MSFlexGrid1.Col = 0
MSFlexGrid1.Text = "title0"
MSFlexGrid1.ColWidth(0) = MSFlexGrid1.Width / 6
MSFlexGrid1.Col = 1
MSFlexGrid1.Text = "title1"
MSFlexGrid1.ColWidth(1) = MSFlexGrid1.Width / 6
MSFlexGrid1.Col = 2
MSFlexGrid1.Text = "title2"
MSFlexGrid1.ColWidth(2) = MSFlexGrid1.Width / 6
MSFlexGrid1.Col = 3
MSFlexGrid1.Text = "title3"
MSFlexGrid1.ColWidth(3) = MSFlexGrid1.Width / 12
MSFlexGrid1.Col = 4
MSFlexGrid1.Text = "title4"
MSFlexGrid1.ColWidth(4) = MSFlexGrid1.Width / 3
MSFlexGrid1.Col = 5
MSFlexGrid1.Text = "title5"
MSFlexGrid1.ColWidth(5) = MSFlexGrid1.Width / 12
MSFlexGrid1.Col = 1
For i = 1 To 8
MSFlexGrid1.Row = i
MSFlexGrid1.ColSel = MSFlexGrid1.Cols - 1
If i Mod 2 = 0 Then
MSFlexGrid1.CellBackColor = vbYellow ' 黄色 Else
MSFlexGrid1.CellBackColor = vbBlue ' 兰色
End If
MSFlexGrid1.TextMatrix(i, 0) = i
For j = 1 To 5
MSFlexGrid1.TextMatrix(i, j) = Int(18 * Rnd) + 1
Next j
Next i
应用举例:
例1:建立一个窗体,在窗体上增加TreeView,ListView和MSFlexGrid控件,并按照知识要点所举例子进行控件编程练习。
1.建立一个标准exe的工程1,选择菜单-〉工程-〉部件,部件选择画面,选择Microsoft FlexGrid Control 6.0,Microsoft Control Common
Controls 6.0(SP4)和Microsoft Control Common Controls-2 6.0 (SP4),点击确认。参见如下图10-2:
图10-2 工程-〉部件选择
2.在窗体Form1上添加TreeView,ListView和MSFlexGrid控件,按照上面关于TreeView,ListView和MSFlexGrid的例子编程,运行结果参见如下图10-3:
图10-3 TreeView,ListView和MsFlexGrid的例子
例2:数据库中一个表具有如下表格式,请使用嵌套循环方式,编程序实现
1.在上面建立的工程1中,增加一个窗体Form2,向窗体Form2中增加TreeView控件。
2.在该项目当前目录下,建立一个Access数据库db1.mdb,具有如上表所示数据的Station表。
3.在工程添加一个数据环境,更改名称为DE1,数据连接对象为Conn;点击Conn对象,更改其数据连接属性为连接Access数据库Rptdb.mdb。步骤参见图10-4,图10-5,图10-6。
图10-4 连接数据库Access—选择驱动程序
图10-5连接数据库Access—选择数据库,用户名和密码
图10-6连接数据库Access—测试连接成功
4.编写TreeView的初始化函数Tree(),代码如下:
Private Sub tree()
Dim nodx As Node
Dim rst, rst1 As ADODB.Recordset
Dim strsql As String
Dim i, j As Long
Dim strkey As String
TreeView1.ImageList = ImageList1
TreeView1.LineStyle = tvwTreeLines
TreeView1.Style = tvwTreelinesPictureText
DE1.Conn.Open
Set rst = New ADODB.Recordset
Set rst1 = New ADODB.Recordset
strsql = "select distinct id , province from station"
rst.Open strsql, DE1.Conn, 3, 1
If rst.RecordCount <> 0 Then
For i = 0 To rst.RecordCount - 1
strkey = Str(rst.Fields("id").Value)
Set nodx = TreeView1.Nodes.Add(, , "k" + strkey, rst.Fields("province").Value, rst.Fields("id").Value)
strsql = "select * from station where id=" & rst.Fields("id").Value
rst1.Open strsql, DE1.Conn, 3, 1
If rst1.RecordCount <> 0 Then
For j = 0 To rst1.RecordCount - 1
Set nodx = TreeView1.Nodes.Add("k" + strkey, tvwChild, rst1.Fields("cityid").Value, rst1.Fields("city").Value, rst.Fields("id").Value)
rst1.MoveNext
Next j
End If
rst1.Close
rst.MoveNext
Next i
End If
End Sub
5. 编写窗体Form2的Load事件程序,实现数据库db1.mdb中表Station的内容加载,代码如下:
Private Sub Form_Load()
Call tree
End Sub
程序运行结果如下图10-7
图10-7 程序运行结果
例3:请将例2中双击树状结构结点后,将属于该结点的数据及其隶属的数据显示在ListView中。
1.在上述工程中,添加一个ListView控件ListView1,编写窗体的listView的初始化函数Listing(),代码如下:
Private Sub listing()
ListView1.ListItems.Clear
ListView1.View = lvwReport
ListView1.Checkboxes = True
ListView1.FullRowSelect = True
ListView1.GridLines = True
ListView1.HotTracking = True
https://www.doczj.com/doc/e213684857.html,belWrap = True
ListView1.ColumnHeaderIcons = ImageList1
ListView1.SmallIcons = ImageList1
ListView1.Icons = ImageList1
ListView1.ColumnHeaders.Add , "h1", "城市", ListView1.Width / 4, 0, 1
ListView1.ColumnHeaders.Add , "h2", "联系人", ListView1.Width / 4, 0, 2
ListView1.ColumnHeaders.Add , "h3", "地址", ListView1.Width / 4, 0, 3
ListView1.ColumnHeaders.Add , "h4", "电话", ListView1.Width / 8, 0, 4
ListView1.ColumnHeaders.Add , "h5", "邮编", ListView1.Width / 8, 0, 5
End Sub
2.编写TreeView1的Click事件,将属于该结点的数据及其隶属的数据显示在ListView中,代码如下:
Private Sub TreeView1_Click()
Dim rs As ADODB.Recordset
Dim strsql As String
Dim i As Long
ListView1.ListItems.Clear
Set rs = New ADODB.Recordset
strsql = "select * from station where cityid like '" + TreeView1.SelectedItem.Key + "%'"
rs.Open strsql, DE1.Conn, 3, 1
If rs.RecordCount <> 0 Then
For i = 0 To rs.RecordCount - 1
ListView1.ListItems.Add i + 1, rs.Fields("cityid").Value, rs.Fields("city").Value, 1, 1
ListView1.ListItems(i + 1).SubItems(1) = IIf(IsNull(rs.Fields("master").Value), "", rs.Fields("master").Value)
ListView1.ListItems(i + 1).SubItems(2) = IIf(IsNull(rs.Fields("telephone").Value), "", rs.Fields("telephone").Value)
ListView1.ListItems(i + 1).SubItems(3) = IIf(IsNull(rs.Fields("address").Value), "", rs.Fields("address").Value)
ListView1.ListItems(i + 1).SubItems(4) = IIf(IsNull(rs.Fields("zip").Value), "", rs.Fields("zip").Value)
rs.MoveNext
Next i
End If
End Sub
当点击树型结构时,程序的运行结果如图10-8。
图10-8 程序运行结果
例4: msflexgrid 控件没有提供直接编辑单个单元内容的功能,然而利用文本框控件的编辑功能可以方便的克服这一局限性。请利用 msflexgrid 控件实现对表格内容进行编辑的方法。
1.新建标准exe工程1,在工程中增加一个MsFlesGrid控件和一个文本框控件。将文本框的 visible 的属性设为 false。在运行中当每次激活表格中的某一单元时均将文本框的大小及位置调整到与被激活的单元的大小及位置相一致,并将该单元的内容赋予文本框。同时将文本框的 visible 的属性设为 true。然后将焦点移到文本框控件上。在该单元的编辑修改结束后,将文本框的内容复制到原单元中,并将文本框的 visible 属性设为false,然后将活动焦点改变到msflexgrid 控件上。为了在运行时使文本框的外观看起来同活动单元完全相同,在设计时需将文本框的 borderstyle 属性设为 0。在滚动表格时,为了使活动单元的内容与表格一起滚动,需将文本框的内容复制到活动单元。然后将文本框的 visible 属性设为 false。
为了实现上述功能,需分别对 msflexgrid 控件的 click 事件编程和 entercell 事件、leavecell 事件、scroll 事件。各部分的程序代码如下。
2.msflexgrid 控件的 click 事件
Private Sub MSFlexGrid1_Click()
If MSFlexGrid1.Row = 0 Or MSFlexGrid1.Col = 0 Then
Text1.Visible = False
Exit Sub
End If
Text1.Text = ″″
Text1.Visible = False
Text1.Top = MSFlexGrid1.Top + MSFlexGrid1.CellTop
Text1.Left = MSFlexGrid1.Left + MSFlexGrid1.CellLeft
Text1.Width = MSFlexGrid1.CellWidth
Text1.Height = MSFlexGrid1.CellHeight
Text1.Text = MSFlexGrid1.Text
Text1.Visible = True
Text1.SetFocus
End Sub
3.msflexgrid 控件的 entercell 事件
Private Sub MSFlexGrid1_EnterCell()
If MSFlexGrid1.MouseRow = 0 Or MSFlexGrid1.MouseCol = 0 Then
Text1.Visible = False
Exit Sub
End If
MSFlexGrid1.Row = MSFlexGrid1.MouseRow
MSFlexGrid1.Col = MSFlexGrid1.MouseCol
Text1.Text = ″″
Text1.Visible = False
Text1.Top = MSFlexGrid1.Top + MSFlexGrid1.CellTop
Text1.Left = MSFlexGrid1.Left + MSFlexGrid1.CellLeft
Text1.Width = MSFlexGrid1.CellWidth
Text1.Height = MSFlexGrid1.CellHeight
Text1.Text = MSFlexGrid1.Text
Text1.Visible = True
Text1.SetFocus
End Sub
4. msflexgrid 控件的 leavecell 事件
Private Sub MSFlexGrid1_LeaveCell()
If Text1.Visible = True Then
MSFlexGrid1.Text = Text1.Text
End If
End Sub
5.msflexgrid 控件的 scroll 事件:
Private Sub MSFlexGrid1_Scroll()
If Text1.Visible = True Then
MSFlexGrid1.Text = Text1.Text
Text1.Visible = False
End If
End Sub
程序运行结果参见图10-9
图10-9程序运行结果
知识扩展:
(1) 保存TreeView数据最简单的形式是XML文件,因为层次型结构是XML 固有的特征。打开“工程”菜单,选择“引用”,在对话框中选中“Microsoft XML v3.0”组件。
每一个节点保存为一个XML元素,节点的属性作为XML元素的属性保存,节点之间的从属关系通过元素的ParentKey属性得以体现。下面是“保存”按钮点击事件句柄的代码。
Private Sub bttnSave_Click()
Dim xmlDoc As DOMDocument30
Set xmlDoc = New DOMDocument30
Dim ElementNode As IXMLDOMElement
Dim RootElementNode As IXMLDOMElement
Set ElementNode = xmlDoc.createElement("NODES")
Set RootElementNode = xmlDoc.appendChild(ElementNode)
Dim TNode As Node
Dim i As Integer
For i = 1 To SmartTreeView.Nodes.Count
Set TNode = SmartTreeView.Nodes(i)
Set ElementNode = xmlDoc.createElement("NODE")
ElementNode.setAttribute "Caption", TNode.Text
ElementNode.setAttribute "Key", TNode.Key
ElementNode.setAttribute "Tag", TNode.Tag
If TNode.Parent Is Nothing Then
ElementNode.setAttribute "ParentKey", ""
Else
ElementNode.setAttribute "ParentKey", TNode.Parent.Key
End If
RootElementNode.appendChild ElementNode
Next
xmlDoc.save ("D:\XMLNodes.xml")
End Sub
读取和恢复节点数据的代码完全一样,这得感谢DOMDocument类的强大功能。首先创建一个DOMDocument对象,然后读入XML文档。接着,利用getElementsByTagName依次获取各个节点,分别设置节点的各个属性,最终装配出原先保存的TreeView,如下所示:
Private Sub bttnLoad_Click()
Dim xmlDoc As DOMDocument30
Set xmlDoc = New DOMDocument30
If Not xmlDoc.Load("D:\XMLNodes.xml") Then
MsgBox "不能读取D:\XMLNodes.xml文件。"
Exit Sub
End If
SmartTreeView.Nodes.Clear
Dim iNode As Integer
Dim newElement As IXMLDOMElement
For iNode = 0 To xmlDoc.getElementsByTagName("NODE").length – 1
Set newElement = xmlDoc.getElementsByTagName ("NODE").Item(iNode)
If newElement.getAttribute("ParentKey") = "" Then
SmartTreeView.Nodes.Add , , _
newElement.getAttribute("Key"), _
newElement.getAttribute("Caption")
Else
SmartTreeView.Nodes.Add _
newElement.getAttribute("ParentKey"), _
tvwChild, newElement.getAttribute("Key"),newElement.getAttribute("Caption") End If
Next
End Sub
培训练习:
(1)请设计一个具有按地区分布的集团分公司的treeview结构地址苦,并编写相关程序,在ListView中显示各个地区的公司信息。
(2)编写一个程序,使MsFlexGrid的单元信息可以通过 Combox下拉列表框选择来更改单元中的内容。
(3)改装知识扩展中的两段代码,是程序成为通用程序,分别为:Sub xmlSave(fname as string,treeV as TreeView)和 Sub xmlLoad(fname as string,treeV as TreeView)。