Vanara/Windows.Forms/Extensions/TreeViewExtension.cs

119 lines
5.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Vanara.PInvoke;
using static Vanara.PInvoke.ComCtl32;
using static Vanara.PInvoke.Shell32;
using static Vanara.PInvoke.User32;
namespace Vanara.Extensions
{
/// <summary>Extension methods for <see cref="TreeView"/> controls.</summary>
public static partial class TreeViewExtension
{
/// <summary>Sets the explorer theme on this <see cref="TreeView"/> instance.</summary>
/// <param name="treeView">The tree view on which to set the theme.</param>
/// <param name="on">If set to <c>true</c> use the Windows Explorer theme, otherwise set to default theme.</param>
public static void SetExplorerTheme(this TreeView treeView, bool on = true)
{
if (Environment.OSVersion.Version.Major >= 6)
{
// Make sure the TVS_NOHSCROLL style is set
treeView.SetStyle((int)TreeViewStyle.TVS_NOHSCROLL);
// Set explorer theme, set critical properties, and set extended styles
treeView.SetWindowTheme(on ? "explorer" : null);
if (!on) return;
treeView.HotTracking = true;
treeView.ShowLines = false;
SendMessage(treeView.Handle, (uint)TreeViewMessage.TVM_SETEXTENDEDSTYLE, (IntPtr)(TreeViewStyleEx.TVS_EX_FADEINOUTEXPANDOS | TreeViewStyleEx.TVS_EX_AUTOHSCROLL), (IntPtr)(TreeViewStyleEx.TVS_EX_FADEINOUTEXPANDOS | TreeViewStyleEx.TVS_EX_AUTOHSCROLL));
}
}
/// <summary>Enumerates child nodes of a given <see cref="TreeNodeCollection"/>.</summary>
/// <param name="nodes">The <see cref="TreeNodeCollection"/> instance from which to start the enumeration.</param>
/// <param name="forAllChildren">if set to <c>true</c> also includes child nodes of all child nodes.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of all <see cref="TreeNode"/> instances in the collection.</returns>
public static IEnumerable<TreeNode> AsEnumerable(this TreeNodeCollection nodes, bool forAllChildren = false)
{
foreach (TreeNode item in nodes)
{
yield return item;
if (forAllChildren)
foreach (var child in item.Nodes.AsEnumerable(true))
yield return child;
}
}
/// <summary>Adds the file system item into a <see cref="TreeView"/> and adds the shell icon associated with it to the <see cref="ImageList"/> of the <c>TreeView</c>.</summary>
/// <param name="tv">The tree view into which to add the item.</param>
/// <param name="nodes">The <see cref="TreeNodeCollection"/> that receives the newly created <see cref="TreeNode"/>.</param>
/// <param name="systemItemPath">The path of the item to add.</param>
/// <returns>A <see cref="TreeNode"/> instance created </returns>
public static TreeNode AddSystemItemAsNode(this TreeView tv, TreeNodeCollection nodes, string systemItemPath)
{
var ext = Path.GetExtension(systemItemPath);
if (string.IsNullOrEmpty(ext))
ext = "5EEB255733234c4dBECF9A128E896A1E";
//ext = fullName.EndsWith("\\") ? "5EEB255733234c4dBECF9A128E896A1E" : "F9EB930C78D2477c80A51945D505E9C4";
else if (ext.Equals(".exe", StringComparison.InvariantCultureIgnoreCase) || ext.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase))
ext = Path.GetFileName(systemItemPath);
if (!tv.ImageList.Images.ContainsKey(ext))
{
try
{
tv.ImageList.Images.Add(ext, IconExtension.GetFileIcon(ext, GetIconSizeFromSize(tv.ImageList.ImageSize)));
}
catch (ArgumentException ex)
{
throw new ArgumentException($"File \"{systemItemPath}\" does" + " not exist!", ex);
}
}
return nodes.Add(systemItemPath, Path.GetFileName(systemItemPath), ext, ext);
}
/// <summary>Enumerates all the nodes in the <see cref="TreeView"/>.</summary>
/// <param name="treeView">The tree view.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of all <see cref="TreeNode"/> instances in this <see cref="TreeView"/>.</returns>
public static IEnumerable<TreeNode> EnumerateAllNodes(this TreeView treeView) => AsEnumerable(treeView.Nodes, true);
/// <summary>Sets the <see cref="TVITEM"/> values.</summary>
/// <param name="node">The <see cref="TreeNode"/> instance for which to set details.</param>
/// <param name="tvItem">The <see cref="TVITEMEX"/> instance.</param>
public static bool SetItem(this TreeNode node, ref TVITEMEX tvItem) => SendMessage(node.TreeView.Handle, TreeViewMessage.TVM_SETITEM, default, ref tvItem).ToInt32() != 0;
/// <summary>Gets the node values.</summary>
/// <param name="node">The <see cref="TreeNode"/> instance for which to get details.</param>
/// <param name="mask">The mask of items to get.</param>
/// <param name="stateMask">The mask of states to get.</param>
/// <returns>A <see cref="TVITEMEX"/> structure with the information.</returns>
public static TVITEMEX GetItem(this TreeNode node, TreeViewItemMask mask = (TreeViewItemMask)0x13FF, TreeViewItemStates stateMask = (TreeViewItemStates)0xFFFF)
{
var tvItem = new TVITEMEX
{
hItem = node.Handle,
mask = mask.SetFlags(TreeViewItemMask.TVIF_HANDLE).SetFlags(TreeViewItemMask.TVIF_TEXT, false),
stateMask = stateMask
};
SendMessage(node.TreeView.Handle, TreeViewMessage.TVM_GETITEM, default, ref tvItem);
return tvItem;
}
private static IconSize GetIconSizeFromSize(Size sz)
{
switch (sz.Height)
{
case 16: return IconSize.Small;
case 48: return IconSize.ExtraLarge;
case 256: return IconSize.Jumbo;
case 32:
default:
return IconSize.Large;
}
}
}
}