Visual Basic 2005 - 如何建立一个主控描绘的TreeView控件
如果您要建立一个主控描绘的 TreeView 控件,也就是说,想要自行撰写程序代码来绘制 TreeView 控件的话,必须将 DrawMode 属性设定成 TreeViewDrawMode.OwnerDrawAll 或 TreeViewDrawMode.OwnerDrawText,并且替 DrawNode 事件处理例程撰写程序代码。
图表 1 所示者是 TreeViewDrawMode 列举类型的成员及其所代表的意义。
成员名称 |
说明 |
|
此为默认值,表示TreeView控件将由操作系统来绘制。 |
OwnerDrawAll |
此表示TreeView控件之节点的所有项目都将由您自行绘制,包括:图示、复选框、加号、减号、以及连接节点的线条。 |
OwnerDrawText |
此表示TreeView控件之节点的卷标部分将由您自行绘制,至于节点的其它项目则由操作系统来绘制,包括:图示、复选框、加号、减号、以及连接节点的线条。 |
图表1
图表2
图表 2 所示者是我们所撰写之程序范例的执行画面,此接口中的TreeView 控件拥有下列特色:
q 如果库存量低于安全存量,便会在节点之卷标文字的右侧额外显示出一个标记文字“低于安全存量,请尽快补货。”。
q 用户除了可以按一下卷标文字来选取节点之外,如果该节点额外显示出标记文字的话,也可以按一下标记文字“低于安全存量,请尽快补货。”来选取节点。
q 标记文字“低于安全存量,请尽快补货。”采用加底线的粗斜体之标楷体字型,而且是黄色的,这些都是我们通过程序代码来自订的。
q 被选取之节点的背景色是绿色,这也是我们通过程序代码来自订的。
显而易见地,本程序示范的TreeView控件是一个主控描绘的TreeView控件,其设计技巧说明如下:
q 请如下所示,建立一个给节点之标记文字使用的Font对象:
Private tagFont As New Font("标楷体", 9, _
FontStyle.Bold Or FontStyle.Italic Or FontStyle.Underline)
q 用户自订程序 LoadDataToTreeView() 负责将数据库数据表中的数据填入TreeView控件中而成为节点。我们以产品名称作为跟节点,并以其它字段的内容作为子节点,而在加入子节点时,会判断「库存量」字段的内容是否低于「安全存量」字段的内容,如果如此的话,便将文字符串“低于安全库存,请尽快补货。”存入该节点的Tag属性中:
While drProduct.Read()
' 以产品名称作为根节点。
rootNode = New TreeNode(drProduct(0).ToString)
TreeView1.Nodes.Add(rootNode)
' 以其它字段的内容作为子节点。
For i As Integer = 1 To nFieldCount – 1
childNode = New TreeNode( _
drProduct.GetName(i) & ":" & drProduct(i).ToString)
TreeView1.Nodes(nRow).Nodes.Add(childNode)
' 如果库存量低于安全库存,则将警示讯息储
' 存于节点的Tag属性中。
If drProduct.GetSqlInt16(3) < drProduct.GetSqlInt16(4) Then
TreeView1.Nodes(nRow).Nodes(0).Tag = _
"低于安全库存,请尽快补货。"
End If
Next
nRow += 1
End While
q 窗体之Load事件处理例程中的下面这一道陈述式,表示要求TreeView控件采用主控描绘:
TreeView1.DrawMode = TreeViewDrawMode.OwnerDrawText
q 替TreeView控件的DrawNode事件处理例程撰写程序代码,以便进行节点的绘制作业:
Private Sub TreeView1_DrawNode(ByVal sender As Object, _
ByVal e As DrawTreeNodeEventArgs) Handles TreeView1.DrawNode
' 绘制被选取之节点的背景色与节点文字。
If (e.State And TreeNodeStates.Selected) <> 0 Then
' 绘制被选取之节点的背景色。如果该节点拥有标记文字
' 「低于安全库存,请尽快补货。」的话,NodeBounds方法
' 会使得醒目提示区域拥有足够的大小来容纳它。
e.Graphics.FillRectangle(Brushes.Green, NodeBounds(e.Node))
' 提取节点字型。如果节点字型未被设定,
' 就使用TreeView的字型。
Dim nodeFont As Font = e.Node.NodeFont
If nodeFont Is Nothing Then
nodeFont = CType(sender, TreeView).Font
End If
' 绘制节点文字。
e.Graphics.DrawString(e.Node.Text, nodeFont, _
Brushes.White, e.Bounds.Left - 2, e.Bounds.Top)
Else
e.DrawDefault = True
End If
' 如果存在节点标记,就将它绘制在节点标签的右侧。
If (e.Node.Tag IsNot Nothing) Then
e.Graphics.DrawString(e.Node.Tag.ToString(), tagFont, _
Brushes.Yellow, e.Bounds.Right + 2, e.Bounds.Top)
End If
' 如果节点拥有焦点,便将焦点矩形绘制得够大
' 以便能够容纳节点卷标文字。
If (e.State And TreeNodeStates.Focused) <> 0 Then
Using focusPen As New Pen(Color.Black)
focusPen.DashStyle = _
System.Drawing.Drawing2D.DashStyle.Dot
Dim focusBounds As Rectangle = NodeBounds(e.Node)
focusBounds.Size = New Size(focusBounds.Width - 1, _
focusBounds.Height - 1)
e.Graphics.DrawRectangle(focusPen, focusBounds)
End Using
End If
End Sub
q 替TreeView控件的MouseDown事件处理例程撰写下列程序代码,使得用户可以按一下标记文字“低于安全库存,请尽快补货。”来选取节点:
' 不论用户按一下节点卷标或节点标记都选取该节点。
Private Sub TreeView1_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles TreeView1.MouseDown
Dim clickedNode As TreeNode = TreeView1.GetNodeAt(e.X, e.Y)
If NodeBounds(clickedNode).Contains(e.X, e.Y) Then
TreeView1.SelectedNode = clickedNode
End If
End Sub
q 用户自订函式NodeBounds能够传回所传递进来之节点的边界范围,包括节点卷标以及节点标记所占用的区域:
Private Function NodeBounds(ByVal node As TreeNode) As Rectangle
' 将传回值设定成正常的节点边界范围。
Dim bounds As Rectangle = node.Bounds
If (node.Tag IsNot Nothing) Then
' 取得TreeView控件的Graphics对象并使用
' 它来计算节点标记的显示宽度。
Dim g As Graphics = TreeView1.CreateGraphics()
Dim tagWidth As Integer = CInt(g.MeasureString( _
node.Tag.ToString(), tagFont).Width) + 6
' 使用计算所得的值来调整节点边界范围。
bounds.Offset(tagWidth \ 2, 0)
bounds = Rectangle.Inflate(bounds, tagWidth \ 2, 0)
End If
Return bounds
End Function
《Visual Basic 2005程序开发与界面设计秘诀》
《Visual C# 2005程序开发与界面设计秘诀》