繁体   English   中英

定制 treeview VB.net

[英]Custom treeview VB.net

我正在寻找在 VB.net 中创建自定义 treeview 控件,我需要做的是有一个标准的 treeview 控件,例如显示系统文件结构的文件夹/名称hover 以上的节点。 因此,例如,如果我在文件夹 Sup2 上 hover,如图所示,则出现橙色图标

例子

我已经做了一些研究,据我所知,我必须重写 onpaint 事件才能实现这一点,但我不确定如何做到这一点。 我还需要将 onclick 事件添加到那个新的橙色图标。

这不专业,但值得一试..

我创建了一个继承自Treeview控件的 class 并覆盖了构造函数 - 更改默认宽度和高度,将DrawMode设置为TreeViewDrawMode.OwnerDrawText

接下来,我处理了TreeView.DrawNode事件,使用PictureBox显示图像并根据当前突出显示的项目更改其位置。

我还处理了PictureBoxClick事件。在该事件下,您可以对突出显示的节点执行任何操作。

我将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

这是一个快速演示:

TreeViewEx

祝你好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM