|
<pre>
using System;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Globalization;
// -----------------------------------------------------------------------------
// Copyright © 2007 Stephen J Whiteley
//
// This source code is provided AS IS, with no warranty expressed or implied,
// including without limitation, warranties of merchantability or
// fitness for a particular purpose or any warranty of title or
// non-infringement. This disclaimer must be passed on whenever the Software
// is distributed in either source form or as a derivative works.
// It may be used for both commercial and non-commercial applications.
//
// -----------------------------------------------------------------------------
public class VistaTreeView : TreeView
{
public VistaTreeView()
{
// ---------------------------------------------------------------------
// New Treeview
// ---------------------------------------------------------------------
//
base.LineColor = SystemColors.GrayText;
_expanderStyle = TreeExpanderStyle.Arrow;
this.BackColor = Color.FromArgb(232, 232, 232);
LoadExpanderImages();
//
// Set the style to double buffered and do all the drawing in
// the paint event (onPaint) of the treeview.
//
// This reduces the flicker, but is a lot more work
//
base.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
base.UpdateStyles();
// Update the styles
//
// Set the treeview styles
SetTreeviewStyle();
}
#region "- Enums -"
public enum TreeExpanderStyle
{
PlusMinus = 0,
Arrow = 1
}
#endregion
#region "- Properties -"
#region "- Private Variables -"
private string CollapsedString = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAARpJREFUOE+lk9tKAmEUhfWhfIiew1eyUkkvPCaNdZdHbPCACIqCklZERQZCZhNZeZylS5jRhvlHcAb2zcD61tqLfzsBOGx9BNgZXdwffCKYLCEgFXF2IcN3XoA3nsNJJAtPOK1Ptd5Z+21NdUDwsgxVBRZLFdPZEj9/CyjjOd6VKd6GEzwPfnH/OobryG0OCEilvWK58SIGMLbRmW6ac+fpG1fynRjgX+9sjE0AY1PcfPiCVLAAnMby+s4UGqfWVZDI98QJjqMZ08LoTHG5PUI82xUDPJH0v7YZmyk08U3rA9HMHsBuYbvOFOcaQ4RTt9YJWFix2Ueq8rgpjDszNp0pDl1bAPjCzMoz/hO+xEPvwdYhbS75UGdNtwLNm+LI5h1FwAAAAABJRU5ErkJggg==";
private string CollapsedArrowString = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAANFJREFUOE+l00kKhDAQheHq+x/KlaALxXkeF04o4g1ep0J3Y0OEiILoIvnyK9QLAD26GHhyKzc7joNpmmhZFtq2jfZ9p+M4lGsvgTOyrqtEVKWXQN/3YGQcR1nCiDZg2zbatsUZmef5HlBVFZqmQdd1smQYBn3AsizkeY6yLP8Q7U8wTRNpmv4QLhAl+gUMRFGEJEnA76KE6rrWBwzDQBAE4KdAKMsyKoriHvBBSJTQF9H+B7zZdV3yPI9836cwDCmOY/2CO7PxaJDkJN85TbX2Db5d1YfJcQ3TAAAAAElFTkSuQmCC";
private Image CollapsedIcon;
private string ExpandedString = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAO9JREFUOE+lk9sKAVEUhnkoD+E5vJJzuHEshzs1DiGUQ0RRigsKJceRcWZ+tppxmjXKTK2bqe/791p7Lz0AnaaPCbSUDI8mK3iiBbgjebjCOThCGdiDKVh9SZi9nFylWvue9wyVBZ5YEaIIXK4ijqcrtvsLeOGMGX/EeH7AYLJDdyjAYDQpC9yRwk+43d/QAnZstWQGN3prWuC890wdW4IrHZ4W2AJpuWfW52cxuNha0gKLP/E1sNdkBmebC1pg9nFv01aCU/W5ukC6KgrmqjN1AbtnNThentIC9sKUhvf5j3yJ/+6DpkV6bPK/yRJ3A/PE7e2oP8DgAAAAAElFTkSuQmCCAPjCzMoz/hO+xEPvwdYhbS75UGdNtwLNm+LI5h1FwAAAAABJRU5ErkJggg==";
private string ExpandedArrowString = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAM9JREFUOE/N0kkKg0AQBdCf+x/KlaALxXkeF04o4g0qXU1sDPQqBhLhI72o17+gH0SEWx8Dd3JrWLa/c/t3Ac/ziOM4Dtm2LWNZFpmmKWMYhsq1tVphmiYw0Pc9tW1LVVVRnueUpilFUURBEEjAdd23tdVhWRZckaZpqCxLiSRJIocFwpfogW3bwMg4juDqXdfRifCwQCCawPd9PbDvO9Z1VQgPMcJ/0QRZloGRMAz1wHEcOJF5njEMA14I6rpGURQSieNYD3z6Hv7oIf1shSf3G9UMQ+Vu/QAAAABJRU5ErkJggg==";
private Image ExpandedIcon;
//
// Text Formatting
private StringFormat TextFormat = new StringFormat(StringFormatFlags.NoWrap);
//
private Pen HighlightBorderPen = new Pen(Color.FromArgb(255, 127, 157, 185));
private Color HighlightColor = Color.FromArgb(255, 204, 230, 255);
private SolidBrush HighlightBrush = new SolidBrush(Color.FromArgb(255, 204, 230, 255));
private Color RootColor = Color.FromArgb(255, 204, 204, 204);
//
private bool _haveImages;
private TreeExpanderStyle _expanderStyle;
private Image _backgroundimage;
private string _lastKnowTopIndex = "";
//
private Brush NodeBrush;
#endregion
#region "- Appearance -"
private Color mBaseColor = Color.FromArgb(0, 5, 10);
// The backing color that the rest of
// the Checkbox is drawn. For a glassier
// effect set this property to Transparent.
[Category("Appearance"), DefaultValue(typeof(Color), "110, 115, 110"), Description("The backing color that the rest of the highlighted area is drawn. For a glassier effect set this property to Transparent.")]
public Color NodeBaseColor
{
get { return mBaseColor; }
set
{
mBaseColor = value;
this.Invalidate();
}
}
private Color mNodeColor = Color.FromArgb(0, 0, 32);
// The bottom color of the Checkbox that
// will be drawn over the base color.
[Category("Appearance"), DefaultValue(typeof(Color), "200, 200, 232"), Description("The bottom color of the highlighted node that will be drawn over the base color.")]
public Color NodeColor
{
get { return mNodeColor; }
set
{
mNodeColor = value;
this.Invalidate();
}
}
private Color mSelectedColor = Color.White;
// The font color of a selected node.
[Category("Appearance"), DefaultValue(typeof(Color), "White"), Description("The font color of a selected node.")]
public Color FontColorSelected
{
get { return mSelectedColor; }
set
{
mSelectedColor = value;
this.Invalidate();
}
}
private Color mHotTrackingColor = Color.Silver;
// The font color of a hovered node if the hottracking is on.
[Category("Appearance"), DefaultValue(typeof(Color), "Silver"), Description("The font color of a hovered node if the hottracking is on.")]
public Color FontColorHotTracking
{
get { return mHotTrackingColor; }
set
{
mHotTrackingColor = value;
this.Invalidate();
}
}
private Font mFontHotTracking = new Font("Arial", 10);
// The hovered node font if the hottracking is on.
[Category("Appearance"), Description("The hovered node font if the hottracking is on.")]
public Font FontHotTracking
{
get { return mFontHotTracking; }
set
{
mFontHotTracking = value;
this.Invalidate();
}
}
#endregion
#region "- Behavior -"
[Category("Behavior"), DefaultValue(typeof(TreeExpanderStyle), "Arrow"), Description("Collapsing arrow style.")]
public TreeExpanderStyle ExpanderStyle
{
get { return _expanderStyle; }
set
{
if (_expanderStyle != value)
{
_expanderStyle = value;
// Load the expander styles and redraw
// the whole treeview
LoadExpanderImages();
base.Invalidate();
}
}
}
#endregion
#region "- Image -"
// The background image
[Category("Image"), DefaultValue(typeof(Image), null), Description("The image displayed on the treeview background."), EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Bindable(true)]
public override Image BackgroundImage
{
get { return _backgroundimage; }
set
{
_backgroundimage = value;
this.Invalidate();
}
}
#endregion
#region "- Shadowed properties -"
public new ImageList ImageList
{
get { return base.ImageList; }
set
{
base.ImageList = value;
_haveImages = (base.ImageList != null);
}
}
[Browsable(true), ReadOnly(false)]
public new Font Font
{
get { return base.Font; }
set
{
base.Font = value;
SetTreeviewStyle();
}
}
[Browsable(false), ReadOnly(true)]
public new TreeViewDrawMode DrawMode
{
get { return base.DrawMode; }
}
[Browsable(false), ReadOnly(true)]
public new bool ShowLines
{
get { return base.ShowLines; }
}
[Browsable(false), ReadOnly(true)]
public new bool ShowRootLines
{
get { return base.ShowRootLines; }
}
[Browsable(false), ReadOnly(true)]
public new bool LabelEdit
{
get { return base.LabelEdit; }
}
[Browsable(false), ReadOnly(true)]
public new bool ShowPlusMinus
{
get { return base.ShowPlusMinus; }
}
[Browsable(false), ReadOnly(true)]
public new Color LineColor
{
get { return base.LineColor; }
}
[Browsable(false), ReadOnly(true)]
public new bool CheckBoxes
{
get { return base.CheckBoxes; }
}
#endregion
#endregion
#region "- Overrided subs -"
protected override void InitLayout()
{
// ---------------------------------------------------------------------
// New Treeview: Initialize the Layout
// ---------------------------------------------------------------------
base.InitLayout();
//
// Overridden properties
base.DrawMode = TreeViewDrawMode.OwnerDrawAll;
base.ShowPlusMinus = true;
base.ShowLines = false;
base.ShowRootLines = true;
base.CheckBoxes = false;
//'
base.LineColor = Color.Black;
}
protected override void OnAfterCollapse(System.Windows.Forms.TreeViewEventArgs e)
{
// ---------------------------------------------------------------------
// After collapsing - redo the node count
// ---------------------------------------------------------------------
base.OnAfterCollapse(e);
}
protected override void OnAfterExpand(System.Windows.Forms.TreeViewEventArgs e)
{
// ---------------------------------------------------------------------
// After Expanding - redo the node count
// ---------------------------------------------------------------------
base.OnAfterExpand(e);
}
protected override void OnParentFontChanged(System.EventArgs e)
{
// ---------------------------------------------------------------------
// Override the OnParentFontChanged event
// ---------------------------------------------------------------------
base.OnParentFontChanged(e);
SetTreeviewStyle();
}
protected override void OnBeforeSelect(System.Windows.Forms.TreeViewCancelEventArgs e)
{
// ---------------------------------------------------------------------
// Override the OnBeforeSelect event
// ---------------------------------------------------------------------
base.OnBeforeSelect(e);
try
{
VistaNode _node = (VistaNode)e.Node;
if (_node.Title) e.Cancel = true;
}
catch (Exception ex)
{
}
}
protected override void OnBeforeExpand(System.Windows.Forms.TreeViewCancelEventArgs e)
{
// ---------------------------------------------------------------------
// Override the OnBeforeExpand event
// ---------------------------------------------------------------------
base.OnBeforeExpand(e);
base.Invalidate();
}
protected override void OnBeforeCollapse(System.Windows.Forms.TreeViewCancelEventArgs e)
{
// ---------------------------------------------------------------------
// Override the OnBeforeCollapse event
// ---------------------------------------------------------------------
try
{
VistaNode _node = (VistaNode)e.Node;
if (_node.Title) e.Cancel = true;
}
catch (Exception ex)
{
}
base.OnBeforeCollapse(e);
base.Invalidate();
}
protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs pevent)
{
// ---------------------------------------------------------------------
// Override the OnPaintBackground event
// ---------------------------------------------------------------------
if (_backgroundimage != null)
{
pevent.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
pevent.Graphics.DrawImage(_backgroundimage, new Rectangle(0, 0, this.Width, this.Height));
}
else
{
LinearGradientBrush b = new LinearGradientBrush(Point.Empty, new PointF(0, this.Height), Color.Black, this.BackColor);
GraphicsPath border = new GraphicsPath();
pevent.Graphics.FillRectangle(b, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
Int32 glowSize = Convert.ToInt32(Convert.ToSingle(this.Height) / 2);
Rectangle glow = new Rectangle(0, this.Height - glowSize - 1, this.Width - 1, glowSize);
b = new LinearGradientBrush(new Point(0, glow.Top - 1), new PointF(0, glow.Bottom), Color.FromArgb(0, Color.FromArgb(0x43, 0x53, 0x7a)), Color.FromArgb(0x43, 0x53, 0x7a));
pevent.Graphics.FillRectangle(b, glow);
}
// If scroll, draw it again
if (this.TopNode != null)
{
if (_lastKnowTopIndex != this.TopNode.Name)
{
this.Invalidate();
_lastKnowTopIndex = this.TopNode.Name;
}
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// ---------------------------------------------------------------------
// Override the OnPaint event to paint the nodes
// ---------------------------------------------------------------------
// MyBase.OnPaint(e)
PaintNodes(base.Nodes, e);
}
#endregion
#region "- Private subs -"
private void LoadExpanderImages()
{
// ---------------------------------------------------------------------
// Loads the included and defined expander images
// ---------------------------------------------------------------------
//
byte[] b = null;
//
// Expanded Image
switch (_expanderStyle)
{
case TreeExpanderStyle.Arrow:
b = Convert.FromBase64String(ExpandedArrowString);
break;
default:
b = Convert.FromBase64String(ExpandedString);
break;
}
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ms.Write(b, 0, b.Length);
ExpandedIcon = Image.FromStream(ms);
//
// Collapsed Image
switch (_expanderStyle)
{
case TreeExpanderStyle.Arrow:
b = Convert.FromBase64String(CollapsedArrowString);
break;
default:
b = Convert.FromBase64String(CollapsedString);
break;
}
ms.Position = 0;
ms.Write(b, 0, b.Length);
CollapsedIcon = Image.FromStream(ms);
//'
ms.Close();
}
private void SetTreeviewStyle()
{
// ---------------------------------------------------------------------
// Sets the various Treeview settings
// ---------------------------------------------------------------------
//
// Unselect the node if it's a parent and are not allowed
// to select parent nodes
//
// ensure a node is selected
if (base.SelectedNode == null)
{
foreach (TreeNode n in base.Nodes)
{
base.SelectedNode = n;
break; // TODO: might not be correct. Was : Exit For
}
}
//
Graphics g = this.CreateGraphics();
SizeF sz = g.MeasureString(CollapsedString.Substring(0, 2), this.Font, 125);
int newHeight = Convert.ToInt32(Math.Ceiling(sz.Height));
if (newHeight > base.ItemHeight) base.ItemHeight = newHeight;
g.Dispose();
//
//'
NodeBrush = new SolidBrush(this.ForeColor);
}
#endregion
#region "- Drawing -"
private void PaintNodes(TreeNodeCollection parentNodes, PaintEventArgs args)
{
// ---------------------------------------------------------------------
// Paint the nodes
// ---------------------------------------------------------------------
//
// Hottracking - find a node over which is the mouse
VistaNode on_item = null;
if (this.HotTracking)
{
Point LocalMousePosition = default(Point);
LocalMousePosition = this.PointToClient(Cursor.Position);
on_item = (VistaNode)this.GetNodeAt(LocalMousePosition);
if (on_item != null)
{
if (on_item.Title) on_item = null;
}
}
foreach (TreeNode n in parentNodes)
{
Rectangle b = new Rectangle(0, n.Bounds.Y, base.ClientSize.Width, n.Bounds.Height);
if (args.ClipRectangle.IntersectsWith(b))
{
// This node intersects with the clip rectangle, so draw it
b = new Rectangle(n.Bounds.X, n.Bounds.Y, base.ClientSize.Width - n.Bounds.X - 1, n.Bounds.Height);
DrawThisNode(args.Graphics, n, b, object.ReferenceEquals(n, on_item));
}
// Check for children nodes
// (Recursively draw the nodes)
if (n.Nodes.Count > 0) PaintNodes(n.Nodes, args);
}
}
private void DrawThisNode(Graphics g, TreeNode node, Rectangle rBounds, bool HotTracked)
{
// ---------------------------------------------------------------------
// Draw a specific node
// ---------------------------------------------------------------------
//
bool selected = node.IsSelected;
// convenience
//
bool hasExpander = false;
// has an Expand/collaps been drawn for this node
Size imageSize = default(Size);
// has an image been drawn for this node
//
//
// Draw selected node background
if (selected) DrawNodeBackground(g, new Rectangle(-2, rBounds.Y, base.Width + 2, rBounds.Height));
//
// Draw expander and image
Rectangle expRect = new Rectangle(rBounds.X - 17, rBounds.Y, rBounds.Width + 12, rBounds.Height);
if (base.ImageList != null)
{
switch (base.ImageList.ImageSize.Width)
{
case 1: // TODO: to 16
expRect = new Rectangle(rBounds.X - base.ImageList.ImageSize.Width - 20, rBounds.Y, rBounds.Width + base.ImageList.ImageSize.Width + 3, rBounds.Height);
break;
case // ERROR: Case labels with binary operators are unsupported : GreaterThan
16:
expRect = new Rectangle(rBounds.X - 2 * base.ImageList.ImageSize.Width - 4, rBounds.Y, rBounds.Width + 2 * base.ImageList.ImageSize.Width - 13, rBounds.Height);
break;
}
}
hasExpander = DrawNodeExpander(g, node, expRect);
imageSize = DrawNodeImage(g, node, new Rectangle(expRect.X + 22, rBounds.Y, expRect.Width - 17, rBounds.Height));
//
//
// Reduce the SIZE of the bounds, used for drawing rectangles
Rectangle rBorder = new Rectangle(expRect.X + imageSize.Width + 22, rBounds.Y, expRect.Width - imageSize.Width - 17 + rBounds.X, rBounds.Height - 1);
//
// Draw the actual Text
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
RectangleF rText = DrawNodeText(g, node, rBorder, selected, HotTracked);
// Draw any node customization
//'
DrawNodeCustom(g, node, rText);
}
private Size DrawNodeImage(Graphics g, TreeNode node, Rectangle r)
{
// ---------------------------------------------------------------------
// Draw the IMAGE associated with this node
// ---------------------------------------------------------------------
if (_haveImages == false) return new Size(0, 0);
VistaNode n = node as VistaNode;
if (n != null)
{
// No images for titles - this code should be changed, but the drawing text code has to be changed as well
if (n.Title) return new Size(0, 0);
}
// Have images: does this NODE have an image?
//
Image img = null;
// Define an image object
//
if (node.IsSelected)
{
// SELECTED
if (node.SelectedImageIndex >= 0)
{
img = base.ImageList.Images[node.SelectedImageIndex];
}
else if (node.SelectedImageKey != null)
{
img = base.ImageList.Images[node.SelectedImageKey];
}
}
else
{
// NOT SELECTED
if (node.ImageIndex >= 0)
{
img = base.ImageList.Images[node.ImageIndex];
}
else if (node.ImageKey != null)
{
img = base.ImageList.Images[node.ImageKey];
}
}
if (img == null) return new Size(0, 0);
// If an image exists, then draw this image at the correct position
Int32 yPosition = r.Y + (base.ItemHeight - img.Height) / 2;
g.DrawImage(img, r.X, yPosition);
// move the text 8px to the right of the image
return new Size(img.Width + 8, img.Height);
}
private bool DrawNodeExpander(Graphics g, TreeNode node, Rectangle r)
{
// ---------------------------------------------------------------------
// Draw the Expander, returning T/F for expander drawn
// ---------------------------------------------------------------------
// Draw the PLUS/MINUS Expand/Collapse Icon if necessary
//If (node.Level = 0 And _collapsibleParent = False) Then Return False
// Set the position for the Expand/collapse icon
bool result = false;
VistaNode n = node as VistaNode;
if (n != null)
{
if (n.Title) return result;
}
if (node.IsExpanded)
{
// Draw the EXPANDED Icon
Int32 yPosition = r.Y + (base.ItemHeight - ExpandedIcon.Height) / 2;
g.DrawImage(ExpandedIcon, r.X, yPosition);
result = true;
}
else
{
if (node.Nodes.Count > 0)
{
// Draw the Collapsed Icon
Int32 yPosition = r.Y + (base.ItemHeight - CollapsedIcon.Height) / 2;
g.DrawImage(CollapsedIcon, r.X, yPosition);
result = true;
}
}
// Has an expander been drawn
return result;
}
private void DrawNodeBackground(Graphics g, Rectangle rBorder)
{
// ---------------------------------------------------------------------
// Draws the background for a Node
// ---------------------------------------------------------------------
DrawBackground(g, rBorder);
DrawOuterStroke(g, rBorder);
DrawInnerStroke(g, rBorder);
DrawHighlight(g, rBorder);
DrawGlossyEffect(g, rBorder);
}
private void DrawBackground(Graphics g, Rectangle r)
{
Int32 alpha = 127;
SolidBrush sb = new SolidBrush(this.NodeBaseColor);
g.FillRectangle(sb, r);
SetClip(g);
g.ResetClip();
sb = new SolidBrush(Color.FromArgb(alpha, this.NodeColor));
g.FillRectangle(sb, r);
}
private void DrawOuterStroke(Graphics g, Rectangle r)
{
Pen p = new Pen(this.NodeColor);
g.DrawLine(p, r.Left, r.Top, r.Right - 1, r.Top);
g.DrawLine(p, r.Left, r.Bottom - 1, r.Right - 1, r.Bottom - 1);
}
private void DrawInnerStroke(Graphics g, Rectangle r)
{
r.X += 1;
r.Y += 1;
r.Width -= 2;
r.Height -= 2;
Pen p = new Pen(this.HighlightColor);
g.DrawLine(p, r.Left, r.Top, r.Right - 1, r.Top);
g.DrawLine(p, r.Left, r.Bottom - 1, r.Right - 1, r.Bottom - 1);
}
private void DrawHighlight(Graphics g, Rectangle rBorder)
{
if (!this.Enabled) return;
Int32 alpha = 150;
Rectangle r = new Rectangle(rBorder.X, rBorder.Y, rBorder.Width, rBorder.Height / 2);
LinearGradientBrush lg = new LinearGradientBrush(r, Color.FromArgb(alpha, this.HighlightColor), Color.FromArgb(alpha / 3, this.HighlightColor), 90.1f, true);
lg.WrapMode = WrapMode.TileFlipXY;
g.FillRectangle(lg, r);
}
private void DrawGlossyEffect(Graphics g, Rectangle rBorder)
{
SetClip(g);
Rectangle r = new Rectangle(rBorder.X, rBorder.Y, rBorder.Width, rBorder.Height);
GraphicsPath glow = CreateTopRoundRectangle(r, 2);
PathGradientBrush gl = new PathGradientBrush(glow);
gl.CenterColor = Color.FromArgb(70, Color.FromArgb(141, 189, 255));
gl.SurroundColors = new Color[] { Color.FromArgb(0, Color.FromArgb(141, 189, 255)) };
g.FillPath(gl, glow);
g.ResetClip();
}
private void SetClip(Graphics g)
{
Rectangle r = this.ClientRectangle;
r.X += 1;
r.Y += 1;
r.Width -= 3;
r.Height -= 3;
g.SetClip(r);
}
private RectangleF DrawNodeText(Graphics g, TreeNode node, Rectangle rBounds, bool selected, bool HotTracked)
{
// ---------------------------------------------------------------------
// Draw the actual node text
// Returns a rectangle where the text was drawn
// ---------------------------------------------------------------------
string txt = node.Text;
bool title = false;
Font NodeFont = default(Font);
if (HotTracked & !selected)
{
NodeFont = this.FontHotTracking;
NodeBrush = new SolidBrush(this.FontColorHotTracking);
}
else if (selected)
{
NodeFont = this.Font;
NodeBrush = new SolidBrush(this.FontColorSelected);
}
else
{
NodeFont = this.Font;
if (node.ForeColor.IsEmpty)
{
NodeBrush = new SolidBrush(this.ForeColor);
}
else
{
NodeBrush = new SolidBrush(node.ForeColor);
}
}
VistaNode n = node as VistaNode;
if (n != null)
{
if (n.NodeFont != null) NodeFont = n.NodeFont;
if (n.Highlighted)
{
NodeBrush = new SolidBrush(n.HighlightedColor);
NodeFont = new Font(NodeFont.FontFamily, NodeFont.Size, FontStyle.Bold);
}
title = n.Title;
}
SizeF sz = g.MeasureString(txt, NodeFont, rBounds.Width, TextFormat);
RectangleF textBounds = default(RectangleF);
if (title)
{
textBounds = new RectangleF(10, rBounds.Y + Convert.ToInt32((rBounds.Height - sz.Height) / 2), rBounds.Width, Convert.ToInt32(sz.Height));
}
else
{
textBounds = new RectangleF(rBounds.X, rBounds.Y + Convert.ToInt32((rBounds.Height - sz.Height) / 2), rBounds.Width, Convert.ToInt32(sz.Height));
}
g.DrawString(node.Text, NodeFont, NodeBrush, textBounds, TextFormat);
// Return the rectanglewhere the text was drawn
textBounds.Width = sz.Width;
return textBounds;
}
private void DrawNodeCustom(Graphics g, TreeNode node, RectangleF rText)
{
// ---------------------------------------------------------------------
// Draw a CUSTOM Node if it's been supplied
// ---------------------------------------------------------------------
VistaNode n = node as VistaNode;
if (n == null) return;
// Nothing is customized
//
// Draw the CUSTOM Properties for this node
Brush br = default(Brush);
// Get the Post-text color
Color col = n.PostTextColor;
// If there isn't a color, use the derault color
Font NodeFont = default(Font);
if (n.Font == null) NodeFont = this.Font; else NodeFont = n.Font;
if (col.IsEmpty)
{
br = NodeBrush;
}
else
{
br = new SolidBrush(n.PostTextColor);
}
if (n.Highlighted)
{
br = new SolidBrush(n.HighlightedColor);
NodeFont = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold);
}
g.DrawString(string.Format(CultureInfo.CurrentUICulture, " {0}", n.PostText), NodeFont, br, rText.X + rText.Width, rText.Y);
}
public GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
{
float x = r.X;
float y = r.Y;
float w = r.Width;
float h = r.Height;
GraphicsPath rr = new GraphicsPath();
rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
rr.AddLine(x + r1, y, x + w - r2, y);
rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
rr.AddLine(x + w, y + r2, x + w, y + h - r3);
rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
rr.AddLine(x + w - r3, y + h, x + r4, y + h);
rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
rr.AddLine(x, y + h - r4, x, y + r1);
return rr;
}
#endregion
#region "- private functions -"
// Creates a rectangle rounded on the top
// <param name="rectangle">Base rectangle</param>
// <param name="radius">Radius of the top corners</param>
// <returns>Rounded rectangle (on top) as a GraphicsPath object</returns>
private GraphicsPath CreateTopRoundRectangle(Rectangle rectangle, Int32 radius)
{
GraphicsPath path = new GraphicsPath();
Int32 l = rectangle.Left;
Int32 t = rectangle.Top;
Int32 w = rectangle.Width;
Int32 h = rectangle.Height;
Int32 d = radius << 1;
path.AddArc(l, t, d, d, 180, 90);
// topleft
path.AddLine(l + radius, t, l + w - radius, t);
// top
path.AddArc(l + w - d, t, d, d, 270, 90);
// topright
path.AddLine(l + w, t + radius, l + w, t + h);
// right
path.AddLine(l + w, t + h, l, t + h);
// bottom
path.AddLine(l, t + h, l, t + radius);
// left
path.CloseFigure();
return path;
}
#endregion
}
[Serializable()]
public class VistaNode : TreeNode
{
private string _postText;
private Color _postTextColor;
private bool _postTextShow;
private Font _font;
private bool _highlighted;
private Color _highlightedColor;
private bool _title;
// ---------------------------------------------------------------------
// Constructor for Serialization
// ---------------------------------------------------------------------
protected VistaNode(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
public VistaNode()
{
_postTextColor = Color.Empty;
_postTextShow = true;
_postText = string.Empty;
_font = null;
_highlighted = false;
_highlightedColor = Color.Empty;
_title = false;
}
public string PostText
{
get { return _postText; }
set
{
_postText = value;
ForceUpdate();
}
}
public Color PostTextColor
{
get { return _postTextColor; }
set
{
_postTextColor = value;
ForceUpdate();
}
}
public Font Font
{
get { return _font; }
set
{
_font = value;
ForceUpdate();
}
}
public Color HighlightedColor
{
get { return _highlightedColor; }
set
{
_highlightedColor = value;
ForceUpdate();
}
}
public bool Highlighted
{
get { return _highlighted; }
set
{
_highlighted = value;
ForceUpdate();
}
}
public bool PostTextShow
{
get { return _postTextShow; }
set
{
_postTextShow = value;
ForceUpdate();
}
}
public bool Title
{
get { return _title; }
set { _title = value; }
}
private void ForceUpdate()
{
// ---------------------------------------------------------------------
// Force a change in the node text to update the
// node in the parent treeview
// Rather crude, but appears to work
// ---------------------------------------------------------------------
base.Text = base.Text;
}
}
</pre>
|
|
|
|