Results 1 to 22 of 22

Thread: vs ToolBox-Type Control

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    vs ToolBox-Type Control

    GroupedTreeView Control and Accessories . . .

    OK. This is my first attempt at a custom control. I still consider myself a beginner, but I have to say, not too shabby for a first attempt.

    The Control uses version 3.5 of the .NET Framework, and the project file attachments are in vs2008. All Compiled elements have been removed.

    I have tried to re-create the basic look and functionality of the vs2008 Toolbox control, with reasonable success. The control inherits from TreeView, and can be used in much the same way as you would use a standard treeview control:

    1. The GroupedTreeView “Headers” are simply the Level 0 TreeNodes. When you populate this control, the first level of the node hierarchy is this.
    2. There is only one lower node level (Level 1). I did this on purpose, so that you get “headers” and “Items”.
    3. The GroupedTreeView.Imagelist is used to associate images/Icons with items at Level 1. Attempting to associate an image with a Level 0 node produces no change.
    4. The nodes for the control (Level 0 AND level 1) are entirely owner-drawn.
    5. There is a Class Called “GroupedTreeViewColorScheme” which defines pre-determined color schemes for the control. Due to the use of gradients, and the complexity of the TreeView Base Class, I decided it would be best this way. There are probably better ways to do it.

    Events and User interaction

    The Event handling for this was tricky, and I am hoping someone out there can find a better way to handle this. Apparently, the TreeNode Class responds differently depending on WHERE in the node area a mouseclick occurs. When Clicked over the area that hosts the +/– Symbol, the node expands/collapses, but does not select. When clicked in the area which hosts the Node Text, the node is selected, and expands/Collapses. When a click occurs in the area to the right of the node bounds (Where selection will occur if the FullRowSelect property is set to True), the node registers a double MousenodeClick Event, followed by double toggling of the control. In this case, the end result is no change in the expanded/collapsed status of the node (presumable to make room for the Fullrow select property, allowing users of TreeView to select a node from anywhere in this region without (visible) toggling).

    Unfortunately, I am after a control which models the behavior of the vs Toolbox, which reponds to a click ANYWHERE in the header area by selecting the header (if not selected), and toggling the Header Node. I achieved this, but at a price. There is now a sporadic flicker when one clicks on a selected Header node (most notable during the collapse operation). Not enough to junk the control, but it is annoying.

    I have not found a solution for this, and I have tried MANY different combinations of events and such. I suspect one probably needs to explore handling Windows messages at this point. If anyone has any ideas, or can improve on this, I would LOVE to see what you come up with!

    Drawing the Headers

    I did NOT get all of the detail found in the vs Toolbox Header into this version of the control. It looks pretty good, but this began as an effort to learn my way through control construction. Also, I wanted one of these for my App!!

    I don’t know if I have explained any of this well enough, or if I have tried to explain too much. This is my first codebank posting. I am also going to post it in “Code it better” forum, because I am calling this a finished effort for now, but would LOVE to hear where I could improve, and what could be done better.

    I have attached a vs Project file, and a folder with some images in it. The project file contains three classes and a simple WinForm to demo the control. The Project file has all necessary images set in My.Resources, but I included the stand-alone images for folks to work with.

    I have also attached another vs project file which is the same, except this one is set up as a Class Library project. Since I removed all the compiled elements from the file (The bin and obj folders, per jmcilhinney’s suggestion), you can build the class library version, and play with the control by adding it to your toolbox.

    Again, would love feedback, criticisms, comments, and most of all, pointers on how I SHOULD do it!

    I will follow this post with the code, which may take several more posts in a row.

    Thanks everyone!
    Attached Files Attached Files
    Last edited by RunsWithScissors; Sep 18th, 2009 at 09:37 PM.

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Here is part 1 of the Code for the GroupedTreeViewClass:

    Code:
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Windows.Forms
    
    
    Public Class GroupedTreeView
        Inherits TreeView
    
    
    #Region "Declarations"
    
        'ColorScheme Members:
        'The ColorScheme Class is a custom object created to handle the 
        'Semi-complex color properties of the control.
        Private moColorScheme As GroupedTreeViewColorScheme
        Private mlColorSchemeIndex As GroupedTreeViewColorSchemeIndex = 1
    
        'Header Node Colors:
        Private mColorHeaderGradientDark As Color = Color.FromKnownColor(KnownColor.ButtonShadow)
        Private mColorHeaderGradientLight As Color = Color.FromKnownColor(KnownColor.ControlLight)
        Private mColorHeaderSelectedBackGround As Color = Color.FromKnownColor(KnownColor.InactiveCaptionText)
        Private mColorHeaderSelectedBorder As Color = Color.FromKnownColor(KnownColor.Highlight)
        Private mColorHeaderStandardBorder As Color = Color.SlateGray
        Private mColorNodeSelectedColor As Color = Color.FromKnownColor(KnownColor.InactiveCaptionText)
    
        'Header Node Text Colors:
        Private mColorHeaderStandardText As Color = Color.Black
        Private mColorHeaderSelectedText As Color = Color.Black
    
       'Sub Node Colors:
        Private mColorSubNodeStandardBackGround As Color = Color.FromKnownColor(KnownColor.Control)
        Private mColorSubNodeMouseOverBackGround As Color = Me.BackColor 'Not Implemented
        Private mColorSubNodeSelectedBackGround As Color = Color.FromKnownColor(KnownColor.InactiveCaptionText)
        Private mColorSubNodeSelectedBorder As Color = Color.FromKnownColor(KnownColor.Highlight)
    
        'Sub-Node Text Brushes:
        Private mColorSubNodeStandardText As Color = Color.Black
        Private mColorSubNodeSelectedText As Color = Color.Black
    
        'TreeView Colors:
        Protected mTreeViewBackColor As Color = Color.FromKnownColor(KnownColor.Control)
        Protected mTreeViewForeColor As Color = Color.FromKnownColor(KnownColor.Black)
        Protected mTreeViewBorderColor As Color = Color.FromKnownColor(KnownColor.SlateGray)
    
        Private fntHeaderFont As Font
        Private fntSubNodeFont As Font
    
        'I had to make my own +/- images, which are in My.Resources. For MY project, 
        'I have the images compiled into the resx. I have included the images
        'externally as well, in the file "Image Resources". They are PNG Files . . .
        Private mExpandMeImage As Image = My.Resources.ListExpandPNG9x9_DK
        Private mCollapseMeImage As Image = My.Resources.ListCollapsePNG9x9_DK
    
    
    #Region "About Variable mNode and Tree Events"
        'mNode is used to keep track of the selected/Expanded
        'status of a node; this is necessary because, depanding upon WHERE
        'a mouseclick "lands", a Traditional TreeNode is designed
        'to respond differently. In a normal treeview, a click which occurs
        'over the area which normally contains the +/- icon simply expands/collapses
        'the node, without selecting it. If the Node itself (the area containing the NodeText)
        'is clicked, the node will be selected but not expanded/collapsed. And IF a 
        'traditional node is in FullRowSelect mode, a click in the area to the RIGHT of
        'the Node Text causes the node to be selected but not expanded collapsed. 
    
        'In order to model the vs Toolbox, I wanted a click ANYWHERE within the Drawn boundary
        'of a HEADER node to cause both selection, and toggling of the node. The "Drawn Boundary"
        'DOES NOT CORRESPOND to the Node.Bounds defined by the TreeNode, so a bunch of
        'Event handling B.S. became necessary to manage the interaction between these
        'scenarios. 
    
        'Making this particular peice of the control work "properly" causes some
        'minor, but irritating flicker. 
    
        'IF ANYONE CAN FIND A BETTER WAY (especially one that gets rid of the flicker),
        'PLEASE PM ME and/or post the code!!!
    
    #End Region 'About Variable mNode and Tree Events
        Private mNode As TreeNode
    
        'If this value is set to True via the Public Property
        'AutoCollapse, HeaderNode Selection will automatically collapse
        'All other expanded nodes:
        Private mbooAutoCollapse As Boolean = False
    
    #End Region 'Declarations
    
    
    
    #Region "Constructor/Initialization"
    
        Public Sub New()
    
            With Me
                .SetStyle(ControlStyles.AllPaintingInWmPaint, True)
                .SetStyle(ControlStyles.DoubleBuffer, True)
                .SetStyle(ControlStyles.ResizeRedraw, True)
    
                'Gotta be in OwnerDraw Mode to do this:
                .DrawMode = TreeViewDrawMode.OwnerDrawAll
    
                'Some default Property Settings conducive to the "ToolBox" Look:
                .ItemHeight = 20
                .FullRowSelect = True
                .Scrollable = True
    
                'Initialize the TreeView Imagelist from Jump, 
                'so we can specify 32 bit color depth at the outset:
                .ImageList = New ImageList
                .ImageList.ColorDepth = ColorDepth.Depth32Bit
            End With
    
    
    
        End Sub
    
    
    
        Private Sub GroupedTreeView_DrawNode(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawTreeNodeEventArgs) Handles Me.DrawNode
            Dim nd As TreeNode = e.Node
    
            Me.SuspendLayout()
    
            'Determine the level of the node. ROOT-level nodes
            'are HEADER Nodes, and will be drawn differently
            'than Sub-Level nodes:
            If nd.Level = 0 Then
                'This is a ROOT-LEVEL Node:
    
                DrawHeader(e)
    
            ElseIf nd.Level = 1 Then
                'This is a SUB-NODE:
    
                DrawSubNode(e)
    
            Else
                'For the Moment, I am only allowing the Top level
                '"Header" nodes, and one level of Sub-node "Items":
                Throw New ApplicationException("The GroupedTreeView Control can only host two levels of TreeNodes.")
            End If
    
            Me.ResumeLayout(False)
    
        End Sub
    
    
    
    #End Region 'Constructor/initialization

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 2 of the Code (The "DrawHeader" Method from the GroupedTreeView Class):

    Code:
    #Region "Draw Header Nodes"
    
        Protected Sub DrawHeader(ByVal e As DrawTreeNodeEventArgs)
            'ALL of this can propbably be done better. Also, I have simplified
            'the control's Headers, and the aren't as detailed as the vs Toolbox. 
    
            'After I refine the mechanics of the control (and LOSE THE FLICKER!)
            'I may or may not revisit this . . .
    
            Dim nd As TreeNode = e.Node
            Dim gfx As Graphics = e.Graphics
    
            'The Text Tto display in the Node:
            Dim strText As String = nd.Text
    
            'Establish the Node Location from the Object Bounds
            'Received as a Parameter:
            Dim pt As Point = nd.Bounds.Location
            pt.X = 0
    
            'Adjust the Width to bring the far left
            'edge into the bounds of the TreeView Control:
            Dim sz As Size = nd.Bounds.Size
    
            'The Header Width needs to be adjusted if the TreeView
            'ScrollBar is visible:
            sz.Width = Me.ClientRectangle.Width - 1
    
    
            'Create a rectangle from the location and Size
            'of the node Bounds:
            Dim NodeRect As New RectangleF(pt, sz)
    
            'Derive a Graphics Path from the Rectangle:
            Using NodePath As New Drawing2D.GraphicsPath
                NodePath.AddRectangle(NodeRect)
    
                'Is the HeaderNode Selected?
                If nd.IsSelected Then
    
                    'Define a path to draw a border around the Selected Header:
                    Using BorderPath As New Drawing2D.GraphicsPath
    
                        'Shrink the border just a little:
                        NodeRect.Inflate(-2, -1)
                        BorderPath.AddRectangle(NodeRect)
                        Using br As New Drawing2D.LinearGradientBrush(NodeRect, mColorHeaderSelectedBackGround, mColorHeaderSelectedBackGround, Drawing2D.LinearGradientMode.Vertical)
                            e.Graphics.FillPath(br, BorderPath)
                        End Using
    
                        Dim pn As New Drawing.Pen(mColorHeaderSelectedBorder)
                        e.Graphics.DrawPath(pn, BorderPath)
                    End Using
    
                    'Use the local Function TextDrawLocation to locate the starting point
                    'for the text drawing operation:
                    Dim TextLoc As Point = TextDrawLocation(nd.Bounds.Location, Me.HeaderFont)
    
                    Using brText As New SolidBrush(mColorHeaderSelectedText)
                        e.Graphics.DrawString(strText, Me.HeaderFont, brText, TextLoc.X, TextLoc.Y)
                    End Using
                Else
    
                    'FIll with a vertical gradient:
                    Using br As New Drawing2D.LinearGradientBrush(NodeRect, mColorHeaderGradientLight, mColorHeaderGradientDark, Drawing2D.LinearGradientMode.Vertical)
                        e.Graphics.FillPath(br, NodePath)
                    End Using
    
                    'Define a pen to draw a border around the Selected Header:
                    Dim pn As New Drawing.Pen(mColorHeaderGradientDark)
                    pn.Alignment = Drawing2D.PenAlignment.Inset
    
    
                    'Define a path to draw a border around the Selected HeaderNode:
                    Using BorderPath As New Drawing2D.GraphicsPath
    
                        'Shrink the border just a little:
                        NodeRect.Inflate(0, -1)
                        NodePath.AddRectangle(NodeRect)
    
                        e.Graphics.DrawPath(pn, BorderPath)
                    End Using
    
                    'Use the local Function TextDrawLocation to locate the starting point
                    'for the text drawing operation:
                    Dim TextLoc As Point = TextDrawLocation(nd.Bounds.Location, Me.HeaderFont)
    
                    Using brText As New SolidBrush(mColorHeaderStandardText)
                        e.Graphics.DrawString(strText, Me.HeaderFont, brText, TextLoc.X, TextLoc.Y)
                    End Using
                End If
            End Using
    
            'DRAWING THE EXPANDED/COLLAPSED IMAGES (the +/- Symbols)
            'Is The node Expanded?
            Dim ExpandedImage As Image
            If nd.IsExpanded Then
                ExpandedImage = mCollapseMeImage
            Else
                ExpandedImage = mExpandMeImage
            End If
    
            'Draw the Expander Icon. Use local function Expander location to 
            'locate the upper left-hand corner of the image:
            Dim imgLoc As Point = ExpanderLocation(nd.Bounds.Location, ExpandedImage.Size)
            e.Graphics.DrawImage(ExpandedImage, imgLoc)
    
        End Sub
    
    
    #End Region 'Draw Header Nodes

    [/CODE]

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 3 of Code for The GroupedTreeView Class(The "DrawSubNodes" Method)

    Code:
    #Region "Draw Sub-Nodes"
    
        Protected Sub DrawSubNode(ByVal e As DrawTreeNodeEventArgs)
            Dim nd As TreeNode = e.Node
            Dim gfx As Graphics = e.Graphics
    
            'The Text Tto display in the Node:
            Dim strText As String = nd.Text
    
            'Establish the Node Location from the Object Bounds
            'Received as a Parameter:
            Dim pt As Point = nd.Bounds.Location
            pt.X = 0
    
            'Adjust the Width to bring the far left
            'edge into the bounds of the TreeView Control:
            Dim sz As Size = nd.Bounds.Size
    
            'The Selected Outline of the SubNode needs to be adjusted
            'if the TreeView ScrollBar is visible, so use the Client
            'Rectangle of the The TreeView Control as the Starting point:
            sz.Width = Me.ClientRectangle.Width - 2
    
    
            'Create a rectangle from the location and Size
            'of the node Bounds:
            Dim NodeRect As New RectangleF(pt, sz)
    
            'Derive a Graphics Path from the Rectangle:
    
            If Not NodeRect.IsEmpty Then
    
                'Fine-Tune the alignments of the fill region with the Border:
                Using NodePath As New Drawing2D.GraphicsPath
                    NodeRect.Y = NodeRect.Y + 1
                    NodeRect.Height = NodeRect.Height - 1
                    NodePath.AddRectangle(NodeRect)
    
                    'Is the SubNodeNode Selected?
                    If nd.IsSelected Then
    
                        'Fill with a Uniform gradient:
                        Using br As New Drawing2D.LinearGradientBrush(NodeRect, mColorSubNodeSelectedBackGround, mColorSubNodeSelectedBackGround, Drawing2D.LinearGradientMode.Vertical)
                            e.Graphics.FillPath(br, NodePath)
                        End Using
                        'Define a path to draw a border around the Selected SubNode:
                        Using BorderPath As New Drawing2D.GraphicsPath
    
                            'Shrink the border just a little:
                            NodeRect.Inflate(-0, -1)
    
                            'And move it slightly Down to Accomodate the Shrinkage:
                            NodeRect.Y = NodeRect.Y - 1
    
                            'Then adjust the height again for perfect positioning:
                            NodeRect.Height = NodeRect.Height + 1
                            BorderPath.AddRectangle(NodeRect)
                            Dim pn As New Drawing.Pen(mColorSubNodeSelectedBorder)
                            pn.Alignment = Drawing2D.PenAlignment.Inset
                            e.Graphics.DrawPath(pn, BorderPath)
                        End Using
    
                        'Use the local Function TextDrawLocation to locate the starting point
                        'for the text drawing operation:
                        Dim TextLoc As Point = TextDrawLocation(nd.Bounds.Location, Me.SubNodeFont)
    
                        Using brText As New SolidBrush(mColorHeaderSelectedText)
                            e.Graphics.DrawString(strText, Me.SubNodeFont, brText, TextLoc.X, TextLoc.Y)
                        End Using
                    Else
    
                        'FIll with a vertical gradient:
                        Using br As New Drawing2D.LinearGradientBrush(NodeRect, mColorSubNodeStandardBackGround, mColorSubNodeStandardBackGround, Drawing2D.LinearGradientMode.Vertical)
                            e.Graphics.FillPath(br, NodePath)
                        End Using
    
                        'Use the local Function TextDrawLocation to locate the starting point
                        'for the text drawing operation:
                        Dim TextLoc As Point = TextDrawLocation(nd.Bounds.Location, Me.SubNodeFont)
                        Using brText As New SolidBrush(mColorSubNodeStandardText)
                            e.Graphics.DrawString(strText, Me.SubNodeFont, brText, TextLoc.X, TextLoc.Y)
                        End Using
                    End If
                End Using
    
                'IMAGES FROM NATIVE IMAGE LIST:
                'Does the node have an Image Associated with it in the native image list?
                Dim str As String = nd.ImageKey
                Dim iIndex As Integer = nd.ImageIndex
    
                'Was a valid Image Key or index provided?
                If Not [String].IsNullOrEmpty(str) Then
                    If Not Me.ImageList Is Nothing AndAlso Me.ImageList.Images.Count > 0 Then
                        Try
                            Dim imgListImage As Image = Me.ImageList.Images(nd.ImageKey)
    
                            'Draw the Node Icon. Use local function Expander location to 
                            'locate the upper left-hand corner of the image:
                            Dim imgLoc As Point = ExpanderLocation(nd.Bounds.Location, imgListImage.Size)
                            e.Graphics.DrawImage(imgListImage, imgLoc)
                        Catch ex As Exception
                            Throw New ApplicationException("" & ex.Source & " - " & ex.Message & " - " & My.Resources.ImageList_IndexNotValid)
                        End Try
                    End If
                Else
    
                    'If the key was invalid, test for the index:
                    If iIndex >= 0 Then
                        If Not Me.ImageList Is Nothing AndAlso Me.ImageList.Images.Count > 0 Then
                            Try
                                Dim imgListImage As Image = Me.ImageList.Images(nd.ImageIndex)
    
                                'Draw the Node Icon. Use local function Expander location to 
                                'locate the upper left-hand corner of the image:
                                Dim imgLoc As Point = ExpanderLocation(nd.Bounds.Location, imgListImage.Size)
                                e.Graphics.DrawImage(imgListImage, imgLoc)
                            Catch ex As Exception
                                Throw New ApplicationException("" & ex.Source & " - " & ex.Message & " - " & My.Resources.ImageList_IndexNotValid)
                            End Try
                        End If
    
                    End If
                End If
            End If
    
        End Sub
    
    #End Region 'Draw Sub-Nodes

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 4 of the code for GroupedTreeView (Image and Text positioning functions):

    Code:
    #Region "Image/Text Positioning Functions"
    
    
        ''' <summary>
        ''' Returns an optimal location for the Expander (+/-) Image 
        ''' based upon the size of the image and the height of the 
        ''' Header Node. 
        ''' </summary>
        ''' <param name="NodeLocation"></param>
        ''' <param name="ImageSize"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>    
        Protected Overridable Function ExpanderLocation(ByVal NodeLocation As Point, ByVal ImageSize As Size) As Point
            Dim iTop As Integer
            Dim iLeft As Integer
            Dim dTop As Decimal
            Dim dLeft As Decimal
    
    
            'Err on the side of placemnent to the top:
            dTop = 0.95 * (Me.ItemHeight - ImageSize.Height) / 2
            iTop = NodeLocation.Y + Math.Truncate(dTop)
    
            'Inset the Expansion Selector Image to the left 1.5 times
            'the distance from the Top:
            dLeft = 1.5 * (Me.ItemHeight - ImageSize.Height) / 2
            iLeft = Math.Truncate(dLeft)
    
            'Return a point structure:
            Dim pt As Point
            pt.X = iLeft
            pt.Y = iTop
    
            Return pt
    
        End Function
    
    
        ''' <summary>
        ''' Returns an optimal location for the Header Node Text 
        ''' based upon the size of the image and the height of the 
        ''' Header Node. 
        ''' </summary>
        ''' <param name="NodeLocation"></param>
        ''' <param name="Font"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>    
        Protected Function TextDrawLocation(ByVal NodeLocation As Point, ByVal Font As Font) As Point
    
            Dim iTop As Integer
            Dim iLeft As Integer
            Dim d As Decimal
    
            'Find a decimal value that is 90% of the difference
            'between the height of the header and the height of 
            'the display font:
            d = (Me.ItemHeight - Font.Height) / 2
    
            'Truncate the value to an integer:
            iTop = NodeLocation.Y + Math.Truncate(d)
    
            'Inset the text proportionately to the 
            'height of the Header:
            iLeft = Me.ItemHeight + 5
    
            'Return a Point Structure:
            Dim pt As Point
            pt.X = iLeft
            pt.Y = iTop
    
            Return pt
    
        End Function
    
    
    #End Region 'Image/Text Positioning Functions

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 5 of the code for GroupedTreeView (NodeExpand/Collapse Events)


    Code:
    #Region "Node Expand, Contract Events"
    
    
        Private Sub GroupedTreeView_AfterCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles Me.AfterCollapse
            'If a node has been newly collapsed, it has also just been clicked. 
            'Set the mNode reference to nothing so that if this node is clicked
            'again, the MouseClick or NodeMouseClick Events will Toggle the node:
    
            mNode = Nothing
    
        End Sub
    
        Private Sub GroupedTreeView_AfterExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles Me.AfterExpand
            'If a node has been newly expanded, it has also just been clicked. 
            'Set the mNode reference to nothing so that if this node is clicked
            'again, the the MouseClick or NodeMouseClick Events will Toggle the node:
    
            'If the AutoCollapse Property is True, Collapse all HeaderNodes except the 
            'currently selected one:
            If mbooAutoCollapse Then
                For Each nd As TreeNode In Me.Nodes
    
                    'Only worry about Level 0 Nodes:
                    If nd.Level = 0 Then
                        If Not ReferenceEquals(nd, e.Node) Then
                            nd.Collapse()
                        End If
                    End If
                Next
            End If
            mNode = Nothing
    
        End Sub
    
        Private Sub GroupedTreeView_BeforeSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles Me.BeforeSelect
            'Set mNode to nothing so there will be no
            'equivelent reference to a newly selected node:
            mNode = Nothing
    
        End Sub
    
    
    
    #End Region ' Node Expand, Contract Events

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 6 of code for GroupedTreeView Control (Mouse Events)

    This is where the thing got messy, and where the flicker is happening:

    Code:
    #Region "Mouse Events"
    
        Private Sub GroupedTreeView_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
            Dim pt As Point = e.Location
    
            Me.SuspendLayout()
            For Each nd As TreeNode In Me.Nodes
    
                'A. NODE BOUNDARIES FOR CLICK EVENTS:
                'The Node bounds are NOT the same size as the area we are drawing the node into!
                'Therefore, we need to treat certain areas of the drawn Node differently, since
                'the Tree Control is designed to handle MouseCLick Events within the "Real" Node
                'Bounds differently than the area we have Owner-Drawn. ADDITIONALLY, the TreeView
                'Control we are inheriting from is set up to handle clicks in the area usually 
                'occupied by the expander (+/-) icon separately as well. We have to handle all
                'of these cases and make it seem as if the entire Node is responding uniformly
                'to a Mouse-Click event. 
    
                'NOTE: I used the MouseDown Event because the TreeView seems to only register
                'Mouse CLICK events in areas NOT occupied by a node. 
    
                'B. CLICK EVENTS AND TRACKING NODE STATUS:
                'For OwnerDrawn areas that are NOT contained withing the Control-defined
                'Node Bounds, the click event fires TWICE (Presumably to handle Clicks
                'in FullRowSelect mode). The node is expanded and collapsed. The Module
                'variable mNode is used to keep track of a node's status through this process. 
    
                'Handle MouseClicks in the OwnerDrawn area that are NOT contained within the 
                'actual Node defined by the control:
                Dim rect As New Rectangle(nd.Bounds.Left, nd.Bounds.Y, Me.Width, nd.Bounds.Height)
                If rect.Contains(pt) Then
    
                    'EXCLUDE the area bounded by the real Node:
                    If Not nd.Bounds.Contains(pt) Then
    
                        'Compare the references held by mNode and nd: if they are 
                        'equivelent, then this is the second time the MouseClick Event
                        'has fired in response to the initial user Click. Don't Toggle the control:
                        If Not ReferenceEquals(nd, mNode) Then
    
                            'Toggle the control, and then set mNode equal to
                            'the Clicked Node, so that the next pass will find the two 
                            'equivelent and will not re-toggle the control:
                            nd.Toggle()
                            mNode = nd
                        Else
    
                            'Since the Node was clicked in order to fire the 
                            'Click event and pass a valid node in, the node
                            'must be SELECTED. If it was NEWLY Selected, it 
                            'was toggled during the first pass BEFORE it's selected status was
                            'changed to SELECTED, and mNode was set to reference it. It was skipped for 
                            'toggling on the second pass, so now set mNode to Nothing. Now, if
                            'it is Clicked again in it's Selected state, it will succeed at causing the 
                            'toggle again:
                            If nd.IsSelected Then
                                mNode = Nothing
                            End If
                        End If
                    End If
                End If
            Next
            Me.ResumeLayout(False)
    
        End Sub
    
    
        Private Sub GroupedTreeView_NodeMouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles Me.NodeMouseClick
            Me.SelectedNode = e.Node
            Dim pt As Point = e.Location
            Dim nd As TreeNode = e.Node
    
            'Handle MouseClicks to the area CONTAINED WITHIN the Control-defined Node Bounds.
            'CLicks to this region do NOT double-fire the Click event, so no special handling is
            'required. Simple toggle the control:
    
            'The NodeMouseCLick still fires for Clicks Outside the Control-Defined area. It Double-Fires
            'in these cases, and these are handled by the TreControl_MouseCLick Event. HERE, Exclude
            'Any Click not contained within the control-defined node region:
    
            'Only ROOT Nodes are Expandable:
            If e.Node.Level = 0 Then
                Dim rect As New Rectangle(nd.Bounds.Height, nd.Bounds.Top, nd.Bounds.Width + nd.Bounds.Height, nd.Bounds.Height)
                If rect.Contains(pt) Then
                    nd.Toggle()
                End If
            End If
        End Sub
    
    
    #End Region 'Mouse Events
    
    
    
    #Region "Property Settings"
    
        ''' <summary>
        ''' This Overload turned out not to be needed, but I left it anyway . . .
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads Property ItemHeight()
            Get
                Return MyBase.ItemHeight
            End Get
            Set(ByVal value)
                MyBase.ItemHeight = value
            End Set
        End Property
    
    
        ''' <summary>
        ''' Gets or Sets the Font used to display the text
        ''' in Header (Level(0)) Nodes. 
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property HeaderFont() As Font
            Get
                'If a font has not been set by the client, 
                'initialize the default:
                If fntHeaderFont Is Nothing Then
                    fntHeaderFont = New Font("Tahoma", 8, FontStyle.Bold, GraphicsUnit.Point)
                End If
                Return fntHeaderFont
            End Get
            Set(ByVal value As Font)
                fntHeaderFont = value
            End Set
        End Property
    
    
        ''' <summary>
        ''' Gets or Sets the Font used to display the text
        ''' in Sub-Nodes (Level(1)). 
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property SubNodeFont() As Font
            Get
                If fntSubNodeFont Is Nothing Then
                    fntSubNodeFont = New Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point)
                End If
                Return fntSubNodeFont
            End Get
            Set(ByVal value As Font)
                fntSubNodeFont = value
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or Sets the NodeAutoCollapse Property, which 
        ''' determines if other nodes are collapsed after selection
        ''' of a new node.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property NodeAutoCollapse() As Boolean
            Get
                Return mbooAutoCollapse
            End Get
            Set(ByVal value As Boolean)
                mbooAutoCollapse = value
            End Set
        End Property
    
    #End Region 'Property Settings

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 7 code for GroupedTreeView Control (Colorscheme)

    Code:
    #Region "ColorScheme"
    
        ''' <summary>
        ''' Colorscheme index parameter indicates which of several 
        ''' pre-defined colorschemes to use in drawing the control. 
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property ColorSchemeIndex() As GroupedTreeViewColorSchemeIndex
            Get
                Return mlColorSchemeIndex
            End Get
            Set(ByVal value As GroupedTreeViewColorSchemeIndex)
                If value > 0 Then
                    mlColorSchemeIndex = value
                    moColorScheme = New GroupedTreeViewColorScheme(value)
                    UpdateColorScheme()
                End If
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or Sets color scheme settings for the 
        ''' various control elements, based on the value of
        ''' the ColorSchemeIndex Property.
        ''' </summary>
        ''' <remarks></remarks>
        Protected Sub UpdateColorScheme()
    
            'Due to the complexity of the paint operations for this control, 
            'and the use of gradients in painting the headers, I decided to 
            'use pre-defined color combinations. 
    
            'Additional colorschemes can be defined in the Class GroupedTreeViewCOlorScheme. 
     
    
            'Header Colors:
            mColorHeaderGradientDark = moColorScheme.ColorHeaderGradientDark
            mColorHeaderGradientLight = moColorScheme.ColorHeaderGradientLight
            mColorHeaderSelectedBackGround = moColorScheme.ColorSelectedBackGround
            mColorHeaderSelectedBorder = moColorScheme.ColorHeaderSelectedBorder
            mColorHeaderStandardBorder = moColorScheme.ColorHeaderStandardBorder
            mColorHeaderStandardText = moColorScheme.ColorHeaderStandardText
            mColorHeaderSelectedText = moColorScheme.ColorHeaderSelectedText
    
            'SubNode Colors:
            mColorSubNodeStandardBackGround = moColorScheme.SubNodeStandardBackGround
            mColorSubNodeMouseOverBackGround = moColorScheme.SubNodeMouseOverBackGround
            mColorSubNodeSelectedBackGround = moColorScheme.SubNodeSelectedBackGround
            mColorSubNodeSelectedBorder = moColorScheme.ColorHeaderSelectedBorder
    
            'Colors for Drawing the SubNode Text:
            mColorSubNodeSelectedText = moColorScheme.SubNodeSelectedText
            mColorSubNodeStandardText = moColorScheme.SubNodeStandardText
    
    
            'TreeView Colors:
            mTreeViewBackColor = moColorScheme.TreeViewBackColor
            mTreeViewBorderColor = moColorScheme.TreeViewBorderColor
    
            'Reset the value of the native control BackColor:
            Me.BackColor = mTreeViewBackColor
    
            'Refresh the entire object to reflect the new colorscheme:
            Me.Refresh()
    
        End Sub
    
    
    #End Region 'Color Scheme

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 8 code for Grouped TreeView Control (Dispose)
    Code:
    #Region "Dispose"
    
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    
            Try
                If disposing AndAlso moColorScheme IsNot Nothing Then
                    moColorScheme.Dispose()
                End If
            Catch ex As System.Exception
                MsgBox(ex.Message)
            End Try
    
            If disposing AndAlso fntHeaderFont IsNot Nothing Then
                fntHeaderFont.Dispose()
            End If
    
            If disposing AndAlso fntSubNodeFont IsNot Nothing Then
                fntSubNodeFont.Dispose()
            End If
    
            If disposing AndAlso mExpandMeImage IsNot Nothing Then
                mExpandMeImage.Dispose()
            End If
    
            If disposing AndAlso mCollapseMeImage IsNot Nothing Then
                mCollapseMeImage.Dispose()
            End If
    
            If disposing AndAlso Me.ImageList IsNot Nothing Then
                Me.ImageList.Dispose()
            End If
    
    
            mlColorSchemeIndex = Nothing
            mColorHeaderGradientDark = Nothing
            mColorHeaderGradientLight = Nothing
            mColorHeaderSelectedBackGround = Nothing
            mColorHeaderSelectedBorder = Nothing
            mColorHeaderStandardBorder = Nothing
    
            mColorHeaderStandardText = Nothing
            mColorHeaderSelectedText = Nothing
    
            mColorNodeSelectedColor = Nothing
            mColorSubNodeStandardBackGround = Nothing
            mColorSubNodeMouseOverBackGround = Nothing
            mColorSubNodeSelectedBackGround = Nothing
            mColorSubNodeSelectedBorder = Nothing
    
            mColorSubNodeSelectedText = Nothing
            mColorSubNodeStandardText = Nothing
    
            mTreeViewBackColor = Nothing
            mTreeViewForeColor = Nothing
            mTreeViewBorderColor = Nothing
    
            MyBase.Dispose(disposing)
        End Sub
    
    #End Region 'Dispose
    
    
    End Class

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    OK. Here is a NEW CLass; The GroupedTreeViewCOlorScheme Class. THe Grouped TreeView uses this to set it's color properties (if other than default):

    Part 1 Declarations and Method GetColorScheme:

    Code:
    Imports System.Drawing
    
    
    
    ''' <summary>
    ''' Provides variable representation of combined color sets for the Gourped
    ''' Treeview Control. An enumerated ColorScheme Index informs this class which
    ''' color combinations to assign to the Member Variables. 
    ''' </summary>
    ''' <remarks></remarks>
    Public Class GroupedTreeViewColorScheme
        Implements IDisposable
    
        Private mlColorScheme As GroupedTreeViewColorSchemeIndex = 1
    
    
    #Region "Declarations: Member Variables"
    
        ''' <summary>
        ''' Default Values for All members of the Standard Colorcheme are those that 
        ''' most closely match the vs2008 ToolBox Header:
        ''' </summary>
        ''' <remarks></remarks>
        Protected mColorHeaderGradientDark As Color = Color.FromKnownColor(KnownColor.ButtonShadow)
        Protected mColorHeaderGradientLight As Color = Color.FromKnownColor(KnownColor.ControlLight)
        Protected mColorHeaderSelectedBackGround As Color = Color.FromKnownColor(KnownColor.InactiveCaptionText)
        Protected mColorHeaderSelectedBorder As Color = Color.FromKnownColor(KnownColor.Highlight)
        Protected mColorHeaderStandardBorder As Color = Color.SlateGray
    
        'Color for Drawing the Header Text:
        Private mColorHeaderStandardText As Color = Color.Black
        Private mColorHeaderSelectedText As Color = Color.Black
    
        'Color for Treenodes other than RootNodes:
        Private mColorSubNodeStandardBackGround As Color = Color.FromKnownColor(KnownColor.Control)
        Private mColorSubNodeMouseOverBackGround As Color = Color.FromKnownColor(KnownColor.AliceBlue)
        Private mColorSubNodeSelectedBackGround As Color = Color.FromKnownColor(KnownColor.InactiveCaptionText)
        Private mColorSubNodeSelectedBorder As Color = Color.FromKnownColor(KnownColor.Highlight)
    
        'Color for Drawing the SubNode Text:
        Private mColorSubNodeStandardText As Color = Color.Black
        Private mColorSubNodeSelectedText As Color = Color.Black
    
        'Color for the TreeView Control itself:
        Protected mTreeViewBackColor As Color = Color.FromKnownColor(KnownColor.Control)
        Protected mTreeViewForeColor As Color = Color.FromKnownColor(KnownColor.Black)
        Protected mTreeViewBorderColor As Color = Color.FromKnownColor(KnownColor.SlateGray)
    
    #End Region 'Member Variables
    
    
        Public Sub New()
    
        End Sub
    
        Public Sub New(ByVal ColorSchemeIndex As GroupedTreeViewColorSchemeIndex)
            Me.New()
            GetColorScheme(ColorSchemeIndex)
        End Sub
    
    
        Public Property ColorSchemeIndex() As GroupedTreeViewColorSchemeIndex
            Get
                Return mlColorScheme
            End Get
            Set(ByVal value As GroupedTreeViewColorSchemeIndex)
                mlColorScheme = value
                Me.GetColorScheme(mlColorScheme)
            End Set
        End Property
    
    
    #Region "GetColorScheme"
    
        ''' <summary>
        ''' Sets the colorScheme properties based upon the value of
        ''' the ColorScheme Index passed in. 
        ''' </summary>
        ''' <param name="ColorScheme"></param>
        ''' <remarks></remarks>
        Private Sub GetColorScheme(ByVal ColorScheme As GroupedTreeViewColorSchemeIndex)
    
            Select Case ColorScheme
    
                Case GroupedTreeViewColorSchemeIndex.Standard
    
                    'Header Color:
                    mColorHeaderGradientDark = Color.FromKnownColor(KnownColor.ButtonShadow)
                    mColorHeaderGradientLight = Color.FromKnownColor(KnownColor.ControlLight)
                    mColorHeaderSelectedBackGround = Color.FromKnownColor(KnownColor.InactiveCaptionText)
                    mColorHeaderSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
                    mColorHeaderStandardBorder = Color.SlateGray
                    mColorHeaderStandardText = Color.Black
                    mColorHeaderSelectedText = Color.Black
    
                    'SubNode Color:
                    mColorSubNodeStandardBackGround = Color.FromKnownColor(KnownColor.Control)
                    mColorSubNodeMouseOverBackGround = Color.FromKnownColor(KnownColor.AliceBlue)
                    mColorSubNodeSelectedBackGround = Color.FromKnownColor(KnownColor.InactiveCaptionText)
                    mColorSubNodeSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
    
                    'Color for Drawing the SubNode Text:
                    mColorSubNodeSelectedText = Color.Black
                    mColorSubNodeStandardText = Color.Black
    
    
                    'TreeView Color:
                    mTreeViewBackColor = Color.FromKnownColor(KnownColor.Control)
                    mTreeViewBorderColor = Color.FromKnownColor(KnownColor.SlateGray)
                    mTreeViewForeColor = Color.Black
    
    
                Case GroupedTreeViewColorSchemeIndex.Gray
                    mColorHeaderGradientDark = Color.FromKnownColor(KnownColor.DarkGray)
                    mColorHeaderGradientLight = Color.FromKnownColor(KnownColor.WhiteSmoke)
                    mColorHeaderSelectedBackGround = Color.FromKnownColor(KnownColor.LightSteelBlue)
                    mColorHeaderSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
                    mColorHeaderStandardBorder = Color.SlateGray
                    mColorHeaderStandardText = Color.Black
                    mColorHeaderSelectedText = Color.Black
    
                    'SubNode Color:
                    mColorSubNodeStandardBackGround = Color.FromKnownColor(KnownColor.WhiteSmoke)
                    mColorSubNodeMouseOverBackGround = Color.FromKnownColor(KnownColor.AliceBlue)
                    mColorSubNodeSelectedBackGround = Color.FromKnownColor(KnownColor.LightSteelBlue)
                    mColorSubNodeSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
    
                    'Color for Drawing the SubNode Text:
                    mColorSubNodeSelectedText = Color.Black
                    mColorSubNodeStandardText = Color.Black
    
    
                    'TreeView Color:
                    mTreeViewBackColor = Color.FromKnownColor(KnownColor.WhiteSmoke)
                    mTreeViewBorderColor = Color.FromKnownColor(KnownColor.SlateGray)
                    mTreeViewForeColor = Color.Black
    
                Case GroupedTreeViewColorSchemeIndex.Blue
    
                    mColorHeaderGradientDark = Color.FromKnownColor(KnownColor.CornflowerBlue)
                    mColorHeaderGradientLight = Color.FromKnownColor(KnownColor.White)
                    mColorHeaderSelectedBackGround = Color.FromKnownColor(KnownColor.Cornsilk)
                    mColorHeaderSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
                    mColorHeaderStandardBorder = Color.MediumSlateBlue
                    mColorHeaderStandardText = Color.DarkBlue
                    mColorHeaderSelectedText = Color.DarkBlue
    
                    'SubNode Color:
                    mColorSubNodeStandardBackGround = Color.FromKnownColor(KnownColor.WhiteSmoke)
                    mColorSubNodeMouseOverBackGround = Color.FromKnownColor(KnownColor.AliceBlue)
                    mColorSubNodeSelectedBackGround = Color.FromKnownColor(KnownColor.Cornsilk)
                    mColorSubNodeSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
    
                    'Color for Drawing the SubNode Text:
                    mColorSubNodeSelectedText = Color.DarkBlue
                    mColorSubNodeStandardText = Color.DarkBlue
    
    
                    'TreeView Color:
                    mTreeViewBackColor = Color.FromKnownColor(KnownColor.WhiteSmoke)
                    mTreeViewBorderColor = Color.FromKnownColor(KnownColor.MediumSlateBlue)
                    mTreeViewForeColor = Color.DarkBlue
    
    
                    'Add Additional Color Schemes HERE:
    
                Case Else
                    'Revert to Default:
    
    
                    'Header Color:
                    mColorHeaderGradientDark = Color.FromKnownColor(KnownColor.ButtonShadow)
                    mColorHeaderGradientLight = Color.FromKnownColor(KnownColor.ControlLight)
                    mColorHeaderSelectedBackGround = Color.FromKnownColor(KnownColor.InactiveCaptionText)
                    mColorHeaderSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
                    mColorHeaderStandardBorder = Color.SlateGray
                    mColorHeaderStandardText = Color.Black
                    mColorHeaderSelectedText = Color.Black
    
                    'SubNode Color:
                    mColorSubNodeStandardBackGround = Color.FromKnownColor(KnownColor.Control)
                    mColorSubNodeMouseOverBackGround = Color.FromKnownColor(KnownColor.AliceBlue)
                    mColorSubNodeSelectedBackGround = Color.FromKnownColor(KnownColor.InactiveCaptionText)
                    mColorSubNodeSelectedBorder = Color.FromKnownColor(KnownColor.Highlight)
    
                    'Color for Drawing the SubNode Text:
                    mColorSubNodeSelectedText = Color.Black
                    mColorSubNodeStandardText = Color.Black
    
    
                    'TreeView Color:
                    mTreeViewBackColor = Color.FromKnownColor(KnownColor.Control)
                    mTreeViewBorderColor = Color.FromKnownColor(KnownColor.SlateGray)
                    mTreeViewForeColor = Color.Black
    
            End Select
    
        End Sub
    
    
    #End Region ' Get ColorScheme

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Part 2 of GroupedTreeViewCOlorScheme Class (Property Settings and Dispose)):

    Code:
    #Region "Header BackGround Colors"
    
        Public Property ColorHeaderGradientDark() As Color
            Get
                Return mColorHeaderGradientDark
            End Get
            Set(ByVal value As Color)
                mColorHeaderGradientDark = value
            End Set
        End Property
    
        Public Property ColorHeaderGradientLight() As Color
            Get
                Return mColorHeaderGradientLight
            End Get
            Set(ByVal value As Color)
                mColorHeaderGradientLight = value
            End Set
        End Property
    
    
    
        Public Property ColorSelectedBackGround() As Color
            Get
                Return mColorHeaderSelectedBackGround
            End Get
            Set(ByVal value As Color)
                mColorHeaderSelectedBackGround = value
            End Set
        End Property
    
    
    #End Region ' Header BackGround Color
    
    
    
    #Region "Header Border Colors"
    
        Public Property ColorHeaderSelectedBorder() As Color
            Get
                Return mColorHeaderSelectedBorder
            End Get
            Set(ByVal value As Color)
                mColorHeaderSelectedBorder = value
            End Set
        End Property
    
        Public Property ColorHeaderStandardBorder() As Color
            Get
                Return mColorHeaderStandardBorder
            End Get
            Set(ByVal value As Color)
                mColorHeaderStandardBorder = value
            End Set
        End Property
    
    #End Region ' Header Border Color
    
    
    
    #Region "Header Text Colors"
    
    
        Public Property ColorHeaderSelectedText() As System.Drawing.Color
            Get
                Return mColorHeaderSelectedText
            End Get
            Set(ByVal value As System.Drawing.Color)
                mColorHeaderSelectedText = value
            End Set
        End Property
    
        Public Property ColorHeaderStandardText() As System.Drawing.Color
            Get
                Return mColorHeaderStandardText
            End Get
            Set(ByVal value As System.Drawing.Color)
                mColorHeaderStandardText = value
            End Set
        End Property
    
    #End Region 'Header Text Color
    
    
    
    #Region "TreeView COlors"
    
        Public Property TreeViewBackColor() As System.Drawing.Color
            Get
                Return mTreeViewBackColor
            End Get
            Set(ByVal value As System.Drawing.Color)
                mTreeViewBackColor = value
            End Set
        End Property
    
    
        Public Property TreeViewForeColor() As System.Drawing.Color
            Get
                Return mTreeViewForeColor
            End Get
            Set(ByVal value As System.Drawing.Color)
                mTreeViewForeColor = value
            End Set
        End Property
    
    
    
        Public Property TreeViewBorderColor() As System.Drawing.Color
            Get
                Return mTreeViewBorderColor
            End Get
            Set(ByVal value As System.Drawing.Color)
                mTreeViewBorderColor = value
            End Set
        End Property
    
    
    #End Region ' TreeView Color
    
    
    #Region "SubNode BackGround Colors"
    
        Public Property SubNodeSelectedBackGround() As Color
            Get
                Return mColorSubNodeSelectedBackGround
            End Get
            Set(ByVal value As Color)
                mColorSubNodeSelectedBackGround = value
            End Set
        End Property
    
    
    
        Public Property SubNodeMouseOverBackGround() As Color
            Get
                Return mColorSubNodeMouseOverBackGround
            End Get
            Set(ByVal value As Color)
                mColorSubNodeMouseOverBackGround = value
            End Set
        End Property
    
    
        Public Property SubNodeStandardBackGround() As Color
            Get
                Return mColorSubNodeStandardBackGround
            End Get
            Set(ByVal value As Color)
                mColorSubNodeStandardBackGround = value
            End Set
        End Property
    
    
    #End Region 'SubNode BackGround Color
    
    
    
    #Region "SubNode Selected Border"
    
    
        Public Property SubNodeSelectedBorder() As Color
            Get
                Return mColorSubNodeSelectedBorder
            End Get
            Set(ByVal value As Color)
                mColorSubNodeSelectedBorder = value
            End Set
        End Property
    
    
    #End Region 'SubNode Selected Border
    
    
    #Region "SubNode Text Colors"
    
    
    
        Public Property SubNodeSelectedText() As Color
            Get
                Return mColorSubNodeSelectedText
            End Get
            Set(ByVal value As Color)
                mColorSubNodeSelectedText = value
            End Set
        End Property
    
    
        Public Property SubNodeStandardText() As Color
            Get
                Return mColorSubNodeStandardText
            End Get
            Set(ByVal value As Color)
                mColorSubNodeStandardText = value
            End Set
        End Property
    
    
    #End Region ' SubNode Text Color
    
        Private disposedValue As Boolean = False        ' To detect redundant calls
    
        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
    
                mColorHeaderGradientDark = Nothing
                mColorHeaderGradientLight = Nothing
                mColorHeaderSelectedBackGround = Nothing
                mColorHeaderSelectedBorder = Nothing
                mColorHeaderStandardBorder = Nothing
    
                mColorHeaderStandardText = Nothing
                mColorHeaderSelectedText = Nothing
    
                mColorSubNodeSelectedText = Nothing
                mColorSubNodeStandardText = Nothing
    
                Me.Finalize()
    
            End If
            Me.disposedValue = True
    
        End Sub
    
    #Region " IDisposable Support "
        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
    #End Region
    
    End Class

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    New MOdule:

    A Module, with an ENUM used by the GroupedTreeView and COlorScheme classes:

    Code:
    Public Module modGroupedTreeViewColorSchemes
        Public Enum GroupedTreeViewColorSchemeIndex
            Standard = 1
            Gray = 2
            Blue = 3
            Opal = 4
        End Enum
    End Module

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Last but not least, a FORM, with a GroupedTreeView Control added from the vs toolbox, and some VERY basic implementation code:

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            'Set this to TRUE to auto-collapse unselected nodes(Default is FALSE)
            GroupedTreeView1.NodeAutoCollapse = True
    
            'Play with different COLORSchemes (Default is Brownish/vs standard):
            GroupedTreeView1.ColorSchemeIndex = GroupedTreeViewColorSchemeIndex.Gray
    
            'Populate the control with some demonstration nodes:
            Dim nd As TreeNode
            Dim sNd As TreeNode
    
            'Add Simple Header/SubNodes with no SubNode Icons:
            For i As Integer = 1 To 5
                'Add "Header Nodes":
                nd = Me.GroupedTreeView1.Nodes.Add("Header " & i)
                For j As Integer = 1 To 5
                    'Add "SubNodes" to each header ("toolbox" items):
                    sNd = nd.Nodes.Add("Sub-Node " & j)
                Next
            Next
    
    
            ''NOTE: Uncomment THIS Code block, and Comment out the previous
            ''to see the control with simple Icons:
    
    
            ''The ImageList is initialized automatically; no need to call a constructor on it:
            'GroupedTreeView1.ImageList.Images.Add("Folder", My.Resources.Folder1616_PNG)
    
            'For i As Integer = 1 To 5
            '    nd = Me.GroupedTreeView1.Nodes.Add("Header " & i)
            '    For j As Integer = 1 To 5
            '        sNd = nd.Nodes.Add("Sub-Node " & j, "SUbNode " & j, "Folder")
            '    Next
            'Next
    
        End Sub
    End Class

  14. #14
    ASP.NET Moderator gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: vs ToolBox-Type Control

    Hey,

    Could you perhaps show some screen shots of this control in action?

    Gary

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Uh, yeah. Believe it or not, I wanted to do that when I first posted it, but Couldn't figure out how . . .(Sheepishly).

    Even worse, I was so damn excited that I was able to make the control draw itself and work, that I had not yet USED it in any context other than the Simple test iteration you see here (Basisally, loading it up with a "For i as Integer = 1 To 5 . . ." type structure to see it work. The one you see here is set to use a grey color Scheme. There are (so Far) THREE colorSchemes: Standard (Brownish), Gray, and Blue (Which is a little too bright for my taste . . . working on it).

    Here are some REALLY basic screenshots of what it looks like.

    Note the following:

    A. I have NOT yet implemented the "Drag and Drop" Functionality as found in the vs ToolBox (Actually, much of THAT would need to be implemented on the client/host form side anyway-treeview provides most of what is needed . . .).

    B. I TRIED to show the other side of the sample form, in which there is a Listview control, which populates based on node selection in the Grouped Tree Control. In other words, much as you might use a standard treeview. However, the Image attachment was then too large to upload . . .

    C. Now that this is "done", I am trying to model the rest of my UI (or at least, the current attempt. UI design is HARD to get it RIGHT!). When I have a slightly more impressive view of this control in action, I will post it. I also fully expect to find new issues with the control as I go to use it in a real-world setting. I will post updates as I go.

    D. As I said, the Header Nodes don't yet draw to the same level of detail as those found in the native vs control. Also, I have set the Item height property larger here.

    This is my first attempt at anything like this. Thanks for bearing with me. Feedback is much appreciated!

    The generic folder Icons could be anything else, and in any real-worold implementation would probably be specific to each Sub-node item.
    Attached Images Attached Images    

  16. #16

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    And it looks like I should Grab .Paul's ScreenCapture utility to do this the easy way next time . . .

  17. #17
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: vs ToolBox-Type Control

    Looks nice. I was making a similar control in C# but did not even think about using the Treeview. It works quite nice this way. Mine was completely from scratch which is a lot more work, but also gives me more flexibility.
    You do have the disadvantage that the control flickers a little bit, which is actually the underlying treeview flickering. I don't think there's anything you can do about that. The treeview 'sucks' in that way...

    Also, try to add something to limit the user to only one level of child nodes. I know you tried to do this by simply throwing an exception when a second level of child nodes is detected, but the control breaks after that and keeps throwing exceptions every few seconds.

  18. #18

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Mine was completely from scratch which is a lot more work, but also gives me more flexibility.

    Yeah, tell me. I did the "From scratch" thing FIRST, and it looked good (Slightly better then this, actually), and for the most part, worker pretty good too. However, My original "architecture" was flawed, and I ended up with some really messy event handling issues. It was AFTER I scrapped thatthat I realized I might be able to inherit Treeveiw. As you can see, that came with it's OWN set of problems.



    Also, try to add something to limit the user to only one level of child nodes.
    I agree. Sort of. I wasn't certain I wanted to limit the number of Node generations or not, so I threw the exception in for the moment. I had considered that it might be nice to have a nesting capability for the children. Of course, I ALSO considered that might become ugly and ungainly. SO I left it for now . . .

    I also considered trying to add a separate mechanism for adding "Header" nodes vs "Sub-items". I might still. My "From sctatch" control had this, and there was also a lot more one could do with it in other ways. Since the "Header" was it's own object, which sourced discreet "Selected" "Unselected", "Collapsed" and "Expanded" events, I had originally planned versions in which the Child nodes would derive from ListViewItem OR DataGridViewRow.

    I might still do that. I stilll have the mess of components that went into the Scratch version of this.

    Thanks for the feedback. Watch for updates . . .

  19. #19

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    NickTHissen:

    You do have the disadvantage that the control flickers a little bit, which is actually the underlying treeview flickering. I don't think there's anything you can do about that. The treeview 'sucks' in that way...

    As far as I can tell, the flickering in THIS case occurs as a result of forcing the node to collapse when the click occurs in the area OUTSIDE the TReeView-Defined Event are for the Node (The "FullRowSelect" area, for lack of a better term.

    I one is happy with a control which expands and collapsed only in response to a click on the Expander Icon, there is no flicker. If I remember correctly, the same is true of the area the TReeView THinks is the "Node" (The part you can select if FRS is false.

    I traded the slight flickering for a control which mimics the expand/collapse behavior of the Vs Toolbox. I may end up killing that off though, because I hate the flickering . . .

  20. #20
    ASP.NET Moderator gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: vs ToolBox-Type Control

    Hey,

    Looks good. I will have to take a look at this.

    Gary

  21. #21

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Re: vs ToolBox-Type Control

    Thanks.

    Gawd, it can be horrible to read back thru my posts later and realize that, due to my atrtocious typing, it often sounds like english is my SECOND language.

    EDIT: Like THAT in blue!


    Jesus!

    Thanks for the feedback. Let me know what you think.

  22. #22
    ASP.NET Moderator gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: vs ToolBox-Type Control

    That's why I don't go back and read my posts

    I will let you know if I have a play with this.

    Gary

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width