问题描述
Imports System.Windows.Forms.VisualStyles
Public Class CustomTreeView
Inherits TreeView
Private buttonRect As New Rectangle(80,2,50,26)
Private ReadOnly stringFormat As StringFormat
Public Sub New()
SetStyle(ControlStyles.OptimizedDoubleBuffer,True)
DrawMode = TreeViewDrawMode.OwnerDrawText
ShowLines = False
FullRowSelect = True
ItemHeight = 30
stringFormat = New StringFormat With {
.Alignment = Stringalignment.Near,.LineAlignment = Stringalignment.Center
}
End Sub
Protected Overrides Sub OnDrawNode(ByVal e As DrawTreeNodeEventArgs)
e.Graphics.DrawString(e.Node.Text,Me.Font,New SolidBrush(Me.ForeColor),e.Bounds,stringFormat)
ButtonRenderer.DrawButton(e.Graphics,New Rectangle(e.Node.Bounds.Location + New Size(buttonRect.Location),buttonRect.Size),"btn",True,If(e.Node.Tag IsNot nothing,CType(e.Node.Tag,PushButtonState),PushButtonState.normal))
End Sub
Protected Overrides Sub OnNodeMouseClick(ByVal e As TreeNodeMouseClickEventArgs)
Select Case e.Node.Tag
Case nothing,Is <> PushButtonState.pressed
Return
End Select
e.Node.Tag = PushButtonState.normal
MessageBox.Show(e.Node.Text & " clicked")
' force redraw
e.Node.Text = e.Node.Text
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
Dim tnode As TreeNode = GetNodeAt(e.Location)
If tnode Is nothing Then
Return
End If
Dim btnRectAbsolute As New Rectangle(tnode.Bounds.Location + New Size(buttonRect.Location),buttonRect.Size)
If btnRectAbsolute.Contains(e.Location) Then
tnode.Tag = PushButtonState.pressed
tnode.Text = tnode.Text
End If
End Sub
End Class
告诉我如何只在第一个(主要)点头时显示按钮? 以及如何,当您单击此按钮时,不显示消息,而是调用某个过程?
解决方法
没有内置按钮树节点。但是您可以自己创建一个带有按钮的自定义树节点。此自定义树节点继承自 TreeNode
。为了提高可扩展性,我们为具有 DrawNode
方法的树节点声明了一个接口:
Imports System.Windows.Forms.VisualStyles
Public Interface ICustomDrawTreeNode
Sub DrawNode(ByVal e As DrawTreeNodeEventArgs,buttonState As PushButtonState)
End Interface
我们还创建了一个模块,其中包含在自定义树视图和自定义树节点中使用的一些设置
Module Settings
Public ReadOnly ButtonRect As New Rectangle(80,2,50,26)
Public ReadOnly TextStringFormat = New StringFormat() With {
.Alignment = StringAlignment.Near,.LineAlignment = StringAlignment.Center,.FormatFlags = StringFormatFlags.NoClip Or StringFormatFlags.FitBlackBox Or StringFormatFlags.LineLimit
}
End Module
然后我们可以实现一个像这样的按钮节点
Imports System.Windows.Forms.VisualStyles
Public Class ButtonTreeNode
Inherits TreeNode
Implements ICustomDrawTreeNode
Private ReadOnly buttonText As String
Public Sub New(text As String,buttonText As String)
MyBase.New(text)
Me.buttonText = buttonText
End Sub
Public Sub DrawNode(e As DrawTreeNodeEventArgs,buttonState As PushButtonState) _
Implements ICustomDrawTreeNode.DrawNode
Dim font As Font = e.Node.TreeView.Font
' Draw Text to the left of the button
Dim rect As Rectangle = New Rectangle(
e.Node.Bounds.Location,New Size(Settings.ButtonRect.Left,e.Bounds.Height))
e.Graphics.DrawString(e.Node.Text,font,Brushes.Black,rect,Settings.TextStringFormat)
' Draw the button
rect = New Rectangle(
e.Node.Bounds.Location + Settings.ButtonRect.Location,Settings.ButtonRect.Size)
ButtonRenderer.DrawButton(e.Graphics,buttonText,True,buttonState)
End Sub
End Class
它有一个 Private ReadOnly buttonText As String
来存储按钮的文本。普通节点文本和按钮文本在ButtonTreeNode
的构造函数中传递:
Public Sub New(text As String,buttonText As String)
DrawNode
方法将被调用为 CustomTreeView
中的 OnDrawNode
。
在 CustomTreeView
中,我声明了一个 NodeButtonClick
事件,当单击节点的按钮时将引发该事件。然后您可以在表单中处理此事件。当您在设计器中选择 CustomTreeView
时,此新事件将出现在事件的“操作”部分。
Imports System.ComponentModel
Imports System.Windows.Forms.VisualStyles
Public Class CustomTreeView
Inherits TreeView
<Category("Action")>
Public Event NodeButtonClick(e As TreeNodeMouseClickEventArgs)
Private _isButtonPressed As Boolean
Public Sub New()
SetStyle(ControlStyles.OptimizedDoubleBuffer,True)
DrawMode = TreeViewDrawMode.OwnerDrawText
ShowLines = False
FullRowSelect = True
ItemHeight = 30
End Sub
Protected Overrides Sub OnDrawNode(e As DrawTreeNodeEventArgs)
Dim customDrawNode As ICustomDrawTreeNode = TryCast(e.Node,ICustomDrawTreeNode)
If customDrawNode Is Nothing Then ' Normal text node.
e.Graphics.DrawString(e.Node.Text,Font,e.Node.Bounds,Settings.TextStringFormat)
Else
customDrawNode.DrawNode(e,If(_isButtonPressed,PushButtonState.Pressed,PushButtonState.Normal))
End If
End Sub
Protected Overrides Sub OnNodeMouseClick(e As TreeNodeMouseClickEventArgs)
If _isButtonPressed Then
_isButtonPressed = False
Refresh()
Dim buttonNode = TryCast(e.Node,ButtonTreeNode)
If buttonNode IsNot Nothing Then
RaiseEvent NodeButtonClick(e)
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
Dim buttonNode = TryCast(GetNodeAt(e.Location),ButtonTreeNode)
If buttonNode IsNot Nothing Then
Dim btnRectAbsolute As New Rectangle(
buttonNode.Bounds.Location + Settings.ButtonRect.Location,Settings.ButtonRect.Size)
_isButtonPressed = btnRectAbsolute.Contains(e.Location)
If _isButtonPressed Then
Refresh()
End If
End If
End Sub
End Class
在表格中你可以写
Public Class Form1
Private Sub Form1_Load(sender As Object,e As EventArgs) Handles MyBase.Load
TreeView1.Nodes.Add("Text")
TreeView1.Nodes.Add(New ButtonTreeNode("Caption","Button"))
End Sub
Private Sub TreeView1_NodeButtonClick(e As TreeNodeMouseClickEventArgs) _
Handles TreeView1.NodeButtonClick
MessageBox.Show(e.Node.Text & " clicked")
End Sub
End Class
这会向 TreeView 添加一个普通文本节点和一个自定义按钮节点。它还处理自定义 TreeView 的 NodeButtonClick
。