
I've only really implemented what I needed, so hot tracking is not properly stylized, the Office 2007 palettes don't render great as they don't implement the glass effect amongst many other shortcomings, but it's a passable implementation for my requirements. I didn't bother finding out how to change the border, just used a KryptonTextBox behind my treeview and set my treeview with no border to get the same effect, maybe someone knows how this could be improved. Thought I'd share it, so if anyone wants to use it and makes any improvements we can all benefit. Phil, if you have any quick guides to improve it, much appreciated.
VB version...
- Code: Select all
Imports ComponentFactory.Krypton.Toolkit
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class KryptonTreeView
Inherits TreeView
Dim p_Manager As KryptonManager
Public Sub New()
FormatControl()
' Configure the TreeView control for owner-draw.
Me.DrawMode = TreeViewDrawMode.OwnerDrawText
End Sub
Public Property Manager() As KryptonManager
Get
If p_Manager Is Nothing Then
Try
Dim Form As Form = Me.FindForm
For Each Control In Me.FindForm.Controls
If Control.GetType Is GetType(KryptonManager) Then
p_Manager = Control
End If
Next
Catch ex As Exception
End Try
End If
Return p_Manager
End Get
Set(ByVal value As KryptonManager)
p_Manager = value
End Set
End Property
Private Sub FormatControl()
Me.Font = KryptonManager.CurrentGlobalPalette.GetContentLongTextFont(PaletteContentStyle.ButtonStandalone, PaletteState.ContextNormal)
End Sub
' Draws a node.
Private Sub Me_DrawNode(ByVal sender As Object, ByVal e As DrawTreeNodeEventArgs) Handles Me.DrawNode
e.DrawDefault = False
' Retrieve the node font. If the node font has not been set,
' use the TreeView font.
Dim nodeFont As Font = e.Node.NodeFont
If nodeFont Is Nothing Then
nodeFont = CType(sender, TreeView).Font
End If
' Draw the background and node text for a selected node.
If e.Node Is MyBase.SelectedNode Then '(e.State And TreeNodeStates.Selected) <> 0 Then
' Draw the background of the selected node. The NodeBounds
' method makes the highlight rectangle large enough to
' include the text of a node tag, if one is present.
Dim HighlightGradientColor1 As System.Drawing.Color = Manager.GlobalPalette.GetBackColor1(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedTracking)
Dim HighlightGradientColor2 As System.Drawing.Color = Manager.GlobalPalette.GetBackColor2(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedTracking)
'Dim linGrBrush As New System.Drawing.Drawing2D.LinearGradientBrush(NodeBounds(e.Node), HighlightGradientColor1, HighlightGradientColor2, Drawing2D.LinearGradientMode.Vertical)
'e.Graphics.FillRectangle(linGrBrush, NodeBounds(e.Node))
DrawBlendGradient(e.Graphics, NodeBounds(e.Node), HighlightGradientColor1, HighlightGradientColor1, HighlightGradientColor2, 90)
' Draw the node text.
Dim textBrush As New SolidBrush(KryptonManager.CurrentGlobalPalette.GetContentLongTextColor1(PaletteContentStyle.ButtonListItem, PaletteState.CheckedNormal))
e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, e.Bounds.Left, e.Bounds.Top)
' Draw the focus rectangle large, making
' it large enough to include the text of the node tag, if present.
Dim focusPen As New Pen(Manager.GlobalPalette.GetBorderColor1(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedNormal))
Try
focusPen.Width = 1
Dim focusBounds As New Rectangle(e.Node.Bounds.X, e.Node.Bounds.Y + 1, e.Node.Bounds.Width, e.Node.Bounds.Height - 2)
DrawRoundedRectangle(e.Graphics, focusBounds, KryptonManager.CurrentGlobalPalette.GetBorderRounding(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedNormal), focusPen)
Finally
focusPen.Dispose()
End Try
Else
' Draw the node text.
Dim textBrush As New SolidBrush(KryptonManager.CurrentGlobalPalette.GetContentLongTextColor1(PaletteContentStyle.ButtonListItem, PaletteState.Normal))
e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, e.Bounds.Left, e.Bounds.Top)
End If
End Sub 'Me_DrawNode
Public Sub DrawRoundedRectangle(ByVal objGraphics As Graphics, _
ByVal rect As Rectangle, _
ByVal m_diameter As Integer, _
ByVal Pen As Pen)
If m_diameter = 0 Then
objGraphics.DrawRectangle(Pen, rect)
Exit Sub
End If
Dim m_intxAxis As Integer = rect.X
Dim m_intyAxis As Integer = rect.Y
Dim m_intWidth As Integer = rect.Width
Dim m_intHeight As Integer = rect.Height
'Dim g As Graphics
Dim BaseRect As New RectangleF(m_intxAxis, m_intyAxis, m_intWidth, m_intHeight)
Dim ArcRect As New RectangleF(BaseRect.Location, New SizeF(m_diameter, m_diameter))
'top left Arc
objGraphics.DrawArc(Pen, ArcRect, 180, 90)
objGraphics.DrawLine(Pen, m_intxAxis + CInt(m_diameter / 2), m_intyAxis, m_intxAxis + m_intWidth - CInt(m_diameter / 2), m_intyAxis)
' top right arc
ArcRect.X = BaseRect.Right - m_diameter
objGraphics.DrawArc(Pen, ArcRect, 270, 90)
objGraphics.DrawLine(Pen, m_intxAxis + m_intWidth, m_intyAxis + CInt(m_diameter / 2), m_intxAxis + m_intWidth, m_intyAxis + m_intHeight - CInt(m_diameter / 2))
' bottom right arc
ArcRect.Y = BaseRect.Bottom - m_diameter
objGraphics.DrawArc(Pen, ArcRect, 0, 90)
objGraphics.DrawLine(Pen, m_intxAxis + CInt(m_diameter / 2), m_intyAxis + m_intHeight, m_intxAxis + m_intWidth - CInt(m_diameter / 2), m_intyAxis + m_intHeight)
' bottom left arc
ArcRect.X = BaseRect.Left
objGraphics.DrawArc(Pen, ArcRect, 90, 90)
objGraphics.DrawLine(Pen, m_intxAxis, m_intyAxis + CInt(m_diameter / 2), m_intxAxis, m_intyAxis + m_intHeight - CInt(m_diameter / 2))
End Sub
Public Shared Sub DrawBlendGradient(ByVal g As Graphics, ByVal rect As Rectangle, ByVal LightColor As Color, ByVal DarkColor As Color, ByVal MiddleColor As Color, ByVal Angle As Single)
Dim blend As New ColorBlend(4)
blend.Positions(0) = 0.0F
blend.Colors(0) = LightColor
blend.Positions(1) = 0.8F
blend.Colors(1) = DarkColor
blend.Positions(2) = 0.8F
blend.Colors(2) = DarkColor
blend.Positions(3) = 1.0F
blend.Colors(3) = MiddleColor
Using b As New LinearGradientBrush(rect, blend.Colors(0), blend.Colors(3), Angle)
b.InterpolationColors = blend
g.FillRectangle(Brushes.White, rect)
g.FillRectangle(b, rect)
End Using
End Sub
' Selects a node that is clicked on its label or tag text.
Private Sub Me_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
Dim clickedNode As TreeNode = Me.GetNodeAt(e.X, e.Y)
If clickedNode Is Nothing Then Exit Sub
If NodeBounds(clickedNode).Contains(e.X, e.Y) Then
Me.SelectedNode = clickedNode
End If
End Sub 'Me_MouseDown
' Returns the bounds of the specified node, including the region
' occupied by the node label and any node tag displayed.
Private Function NodeBounds(ByVal node As TreeNode) As Rectangle
' Set the return value to the normal node bounds.
Dim bounds As Rectangle = node.Bounds
Return bounds
End Function 'NodeBounds
End Class
C# Version
- Code: Select all
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using ComponentFactory.Krypton.Toolkit;
using System.Drawing;
using System.Drawing.Drawing2D;
public class KryptonTreeView : TreeView
{
KryptonManager p_Manager;
public KryptonTreeView()
{
MouseDown += Me_MouseDown;
DrawNode += Me_DrawNode;
FormatControl();
// Configure the TreeView control for owner-draw.
this.DrawMode = TreeViewDrawMode.OwnerDrawText;
}
public KryptonManager Manager {
get {
if (p_Manager == null) {
try {
Form Form = this.FindForm;
foreach (object Control_loopVariable in this.FindForm.Controls) {
Control = Control_loopVariable;
if (object.ReferenceEquals(Control.GetType(), typeof(KryptonManager))) {
p_Manager = Control;
}
}
} catch (Exception ex) {
}
}
return p_Manager;
}
set { p_Manager = value; }
}
private void FormatControl()
{
this.Font = KryptonManager.CurrentGlobalPalette.GetContentLongTextFont(PaletteContentStyle.ButtonStandalone, PaletteState.ContextNormal);
}
// Draws a node.
private void Me_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
e.DrawDefault = false;
// Retrieve the node font. If the node font has not been set,
// use the TreeView font.
Font nodeFont = e.Node.NodeFont;
if (nodeFont == null) {
nodeFont = ((TreeView)sender).Font;
}
// Draw the background and node text for a selected node.
//(e.State And TreeNodeStates.Selected) <> 0 Then
if (object.ReferenceEquals(e.Node, base.SelectedNode)) {
// Draw the background of the selected node. The NodeBounds
// method makes the highlight rectangle large enough to
// include the text of a node tag, if one is present.
System.Drawing.Color HighlightGradientColor1 = Manager.GlobalPalette.GetBackColor1(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedTracking);
System.Drawing.Color HighlightGradientColor2 = Manager.GlobalPalette.GetBackColor2(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedTracking);
//Dim linGrBrush As New System.Drawing.Drawing2D.LinearGradientBrush(NodeBounds(e.Node), HighlightGradientColor1, HighlightGradientColor2, Drawing2D.LinearGradientMode.Vertical)
//e.Graphics.FillRectangle(linGrBrush, NodeBounds(e.Node))
DrawBlendGradient(e.Graphics, NodeBounds(e.Node), HighlightGradientColor1, HighlightGradientColor1, HighlightGradientColor2, 90);
// Draw the node text.
SolidBrush textBrush = new SolidBrush(KryptonManager.CurrentGlobalPalette.GetContentLongTextColor1(PaletteContentStyle.ButtonListItem, PaletteState.CheckedNormal));
e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, e.Bounds.Left, e.Bounds.Top);
// Draw the focus rectangle large, making
// it large enough to include the text of the node tag, if present.
Pen focusPen = new Pen(Manager.GlobalPalette.GetBorderColor1(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedNormal));
try {
focusPen.Width = 1;
Rectangle focusBounds = new Rectangle(e.Node.Bounds.X, e.Node.Bounds.Y + 1, e.Node.Bounds.Width, e.Node.Bounds.Height - 2);
DrawRoundedRectangle(e.Graphics, focusBounds, KryptonManager.CurrentGlobalPalette.GetBorderRounding(PaletteBorderStyle.ButtonListItem, PaletteState.CheckedNormal), focusPen);
} finally {
focusPen.Dispose();
}
} else {
// Draw the node text.
SolidBrush textBrush = new SolidBrush(KryptonManager.CurrentGlobalPalette.GetContentLongTextColor1(PaletteContentStyle.ButtonListItem, PaletteState.Normal));
e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, e.Bounds.Left, e.Bounds.Top);
}
}
//Me_DrawNode
public void DrawRoundedRectangle(Graphics objGraphics, Rectangle rect, int m_diameter, Pen Pen)
{
if (m_diameter == 0) {
objGraphics.DrawRectangle(Pen, rect);
return;
}
int m_intxAxis = rect.X;
int m_intyAxis = rect.Y;
int m_intWidth = rect.Width;
int m_intHeight = rect.Height;
//Dim g As Graphics
RectangleF BaseRect = new RectangleF(m_intxAxis, m_intyAxis, m_intWidth, m_intHeight);
RectangleF ArcRect = new RectangleF(BaseRect.Location, new SizeF(m_diameter, m_diameter));
//top left Arc
objGraphics.DrawArc(Pen, ArcRect, 180, 90);
objGraphics.DrawLine(Pen, m_intxAxis + Convert.ToInt32(m_diameter / 2), m_intyAxis, m_intxAxis + m_intWidth - Convert.ToInt32(m_diameter / 2), m_intyAxis);
// top right arc
ArcRect.X = BaseRect.Right - m_diameter;
objGraphics.DrawArc(Pen, ArcRect, 270, 90);
objGraphics.DrawLine(Pen, m_intxAxis + m_intWidth, m_intyAxis + Convert.ToInt32(m_diameter / 2), m_intxAxis + m_intWidth, m_intyAxis + m_intHeight - Convert.ToInt32(m_diameter / 2));
// bottom right arc
ArcRect.Y = BaseRect.Bottom - m_diameter;
objGraphics.DrawArc(Pen, ArcRect, 0, 90);
objGraphics.DrawLine(Pen, m_intxAxis + Convert.ToInt32(m_diameter / 2), m_intyAxis + m_intHeight, m_intxAxis + m_intWidth - Convert.ToInt32(m_diameter / 2), m_intyAxis + m_intHeight);
// bottom left arc
ArcRect.X = BaseRect.Left;
objGraphics.DrawArc(Pen, ArcRect, 90, 90);
objGraphics.DrawLine(Pen, m_intxAxis, m_intyAxis + Convert.ToInt32(m_diameter / 2), m_intxAxis, m_intyAxis + m_intHeight - Convert.ToInt32(m_diameter / 2));
}
public static void DrawBlendGradient(Graphics g, Rectangle rect, Color LightColor, Color DarkColor, Color MiddleColor, float Angle)
{
ColorBlend blend = new ColorBlend(4);
blend.Positions[0] = 0f;
blend.Colors[0] = LightColor;
blend.Positions[1] = 0.8f;
blend.Colors[1] = DarkColor;
blend.Positions[2] = 0.8f;
blend.Colors[2] = DarkColor;
blend.Positions[3] = 1f;
blend.Colors[3] = MiddleColor;
using (LinearGradientBrush b = new LinearGradientBrush(rect, blend.Colors[0], blend.Colors[3], Angle)) {
b.InterpolationColors = blend;
g.FillRectangle(Brushes.White, rect);
g.FillRectangle(b, rect);
}
}
// Selects a node that is clicked on its label or tag text.
private void Me_MouseDown(object sender, MouseEventArgs e)
{
TreeNode clickedNode = this.GetNodeAt(e.X, e.Y);
if (clickedNode == null)
return;
if (NodeBounds(clickedNode).Contains(e.X, e.Y)) {
this.SelectedNode = clickedNode;
}
}
//Me_MouseDown
// Returns the bounds of the specified node, including the region
// occupied by the node label and any node tag displayed.
private Rectangle NodeBounds(TreeNode node)
{
// Set the return value to the normal node bounds.
Rectangle bounds = node.Bounds;
return bounds;
}
//NodeBounds
}
