[英]Custom treeview VB.net
我正在寻找在 VB.net 中创建自定义 treeview 控件,我需要做的是有一个标准的 treeview 控件,例如显示系统文件结构的文件夹/名称hover 以上的节点。 因此,例如,如果我在文件夹 Sup2 上 hover,如图所示,则出现橙色图标
我已经做了一些研究,据我所知,我必须重写 onpaint 事件才能实现这一点,但我不确定如何做到这一点。 我还需要将 onclick 事件添加到那个新的橙色图标。
这不专业,但值得一试..
我创建了一个继承自Treeview
控件的 class 并覆盖了构造函数 - 更改默认宽度和高度,将DrawMode
设置为TreeViewDrawMode.OwnerDrawText
。
接下来,我处理了TreeView.DrawNode
事件,使用PictureBox
显示图像并根据当前突出显示的项目更改其位置。
我还处理了PictureBox
的Click
事件。在该事件下,您可以对突出显示的节点执行任何操作。
我将My.Resources
中的图像用于ImageList.Images(0)
和PictureBox.Image
Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim trv As New MyTreeView
trv.Nodes.Add("Suppliers")
trv.Nodes(0).Nodes.Add("Sup 1")
trv.Nodes(0).Nodes.Add("Sup 2")
trv.Nodes(0).Nodes.Add("Sup 3")
trv.Nodes(0).Nodes.Add("Sup 4")
trv.Nodes(0).Nodes.Add("Sup 5")
Controls.Add(trv)
End Sub
End Class
'Class Starts Here
Public Class MyTreeView
Inherits TreeView
WithEvents myImage As PictureBox
Dim activeItem As TreeNode 'Variable to store active TreeNode
Public Sub New()
MyBase.New() 'Call the base class constructor
'And set some values
Height = 300
Width = 300
Location = New Point(50, 50)
DrawMode = TreeViewDrawMode.OwnerDrawText 'Very neccesary
AddHandler DrawNode, AddressOf MyTreeViewDrawNode
'Add event handlers
AddHandler AfterCollapse, AddressOf MyTreeViewCollapsed
'Set HotTracking event to true to allow for MouseHover
HotTracking = True
ImageList = new ImageList
ImageList.Images.Add(My.Resources.FolderImage)
ImageIndex = 0
Font = New Font(Font.FontFamily, 10)
'Initialize picturebox
myImage = New PictureBox() With
{
.Image = My.Resources.editPencilImage,
.SizeMode = PictureBoxSizeMode.Zoom,
.Size = New Size(10, 10),
.Visible = False
}
Controls.Add(myImage)
End Sub
Private Sub MyTreeViewCollapsed(sender As Object, e As TreeViewEventArgs)
myImage.Visible = False
End Sub
Sub ImageClicked(sender As Object, e As EventArgs) Handles myImage.Click
If (Not activeItem Is Nothing) Then
MessageBox.Show("Clicked Item - " & activeItem.Text)
End If
End Sub
Private Sub MyTreeViewDrawNode(sender As Object, e As DrawTreeNodeEventArgs)
e.DrawDefault = True
If (e.State = TreeNodeStates.Hot) Then
myImage.Visible = True
activeItem = e.Node
Dim tmpSize = TextRenderer.MeasureText(e.Node.Text, Font)
myImage.Location = New Point(e.Node.Bounds.Location.X + tmpSize.Width, e.Node.Bounds.Location.Y)
End If
End Sub
End Class
我想下面的例子会给你一些提示和技巧。
Option Explicit On
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Public Class TreeViewEx
Inherits TreeView
#Region "API"
Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wp As IntPtr,
ByVal lp As IntPtr) As IntPtr
End Function
#End Region
#Region "Private Fields"
Private ReadOnly RightImage As Bitmap
Private ReadOnly NSF As StringFormat
Private HoverNode As TreeNode
Private RightImageRect As Rectangle
#End Region
#Region "Constructors"
Sub New()
DrawMode = TreeViewDrawMode.OwnerDrawText
RightImage = New Bitmap(My.Resources.Modify)
NSF = New StringFormat With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.NoWrap
}
End Sub
#End Region
#Region "Paint"
Protected Overrides Sub OnDrawNode(e As DrawTreeNodeEventArgs)
MyBase.OnDrawNode(e)
If e.Node Is Nothing Then Return
Dim rect As Rectangle = e.Bounds : rect.Inflate(0, 1)
If Not ClientRectangle.IntersectsWith(rect) Then
Return
End If
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.HighQuality
G.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
'Option1: If you want to draw different background color for the selected node.
'If (e.State And TreeNodeStates.Selected) = TreeNodeStates.Selected Then
' Using br As New SolidBrush(Color.LightSteelBlue) '<- suit yourself!
' G.FillRectangle(br, rect)
' End Using
'Else
' Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
' G.FillRectangle(br, rect)
' End Using
'End If
'Option2: If you don't want Option1.
Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
G.FillRectangle(br, rect)
End Using
Using br As New SolidBrush(If(e.Node.ForeColor.Equals(Color.Empty), ForeColor, e.Node.ForeColor))
G.DrawString(e.Node.Text, If(e.Node.NodeFont, Font), br, rect, NSF)
End Using
If ReferenceEquals(e.Node, HoverNode) Then
RightImageRect = New Rectangle(rect.Right + 5,
rect.Y + ((rect.Height - RightImage.Height) / 2),
rect.Height - 4, rect.Height - 4)
G.DrawImage(RightImage,
RightImageRect,
New Rectangle(0, 0, RightImage.Width, RightImage.Height),
GraphicsUnit.Pixel)
End If
End Sub
#End Region
#Region "Other Events"
'You need this to reduce the flickering.
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
SendMessage(
Handle,
TVM_SETEXTENDEDSTYLE,
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER),
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER)
)
MyBase.OnHandleCreated(e)
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
Dim node = GetNodeAt(e.Location)
If node IsNot Nothing Then
'Avoid unnecessary Invalidate() calls.
If Not ReferenceEquals(node, HoverNode) Then
HoverNode = node
Invalidate()
End If
Else
'Avoid unnecessary Invalidate() calls.
If HoverNode IsNot Nothing Then
HoverNode = Nothing
Invalidate()
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
MyBase.OnMouseDown(e)
If e.Button = MouseButtons.Left AndAlso
RightImageRect.Contains(e.Location) Then
'Notify the container to do something.
OnEditButtonClicked()
End If
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
Invalidate()
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
RightImage.Dispose()
NSF.Dispose()
End If
End Sub
#End Region
#Region "Custom Events"
Public Class EditButtonClickArgs
Inherits EventArgs
Public Property Node As TreeNode
Sub New(node As TreeNode)
Me.Node = node
End Sub
End Class
''' <summary>
''' Raised when the right image is clicked.
''' </summary>
Public Event EditButtonClicked As EventHandler(Of EditButtonClickArgs)
''' <summary>
''' Raises the <see cref="EditButtonClicked"/> events.
''' </summary>
Protected Overridable Sub OnEditButtonClicked()
RaiseEvent EditButtonClicked(Me, New EditButtonClickArgs(HoverNode))
End Sub
#End Region
End Class
在包含新 TreeViewEx 控件的窗体中,您可以处理EditButtonClicked
以执行必要的操作:
Public Class Form1
Inherits Form
Private Sub TreeViewEx1_EditButtonClicked(sender As Object, e As TreeViewEx.EditButtonClickArgs) Handles TreeViewEx1.EditButtonClicked
'Do something with the e.Node
End Sub
End Class
这是一个快速演示:
祝你好运。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.