WinForms TreeView:检查复选框是否隐藏

本文关键字:是否 隐藏 复选框 检查 TreeView WinForms | 更新日期: 2023-09-27 17:50:46

我正在使用以下解决方案来显示或隐藏TreeView中的复选框:

https://stackoverflow.com/a/22230299/1583649

然而,现在我想知道如何检查复选框是否隐藏或不为节点。

例如,我希望能够设置复选框。仅对在选中顶级节点时具有复选框可见的顶级节点的子节点检查为true(或false)。有办法做到这一点吗?

WinForms TreeView:检查复选框是否隐藏

TVM_GETITEM或TVM_GETITEMSTATE可用于获取状态,然后可用于推断节点上的哪个复选框图像(无,选中或未选中)。下面是一个扩展类,它提供了您需要的两个方法。

用法:

// something like this
var treeNode = ...;
if (treeNode.IsCheckBoxVisible())
    treeNode.SetIsCheckBoxVisible(false);
else
    treeNode.SetIsCheckBoxVisible(true);

扩展:

public static class TreeViewExtensions
{
    /// <summary>
    /// Gets a value indicating if the checkbox is visible on the tree node.
    /// </summary>
    /// <param name="node">The tree node.</param>
    /// <returns><value>true</value> if the checkbox is visible on the tree node; otherwise <value>false</value>.</returns>
    public static bool IsCheckBoxVisible(this TreeNode node)
    {
        if (node == null)
            throw new ArgumentNullException("node");
        if (node.TreeView == null)
            throw new InvalidOperationException("The node does not belong to a tree.");
        var tvi = new TVITEM
            {
                hItem = node.Handle,
                mask = TVIF_STATE
            };
        var result = SendMessage(node.TreeView.Handle, TVM_GETITEM, node.Handle, ref tvi);
        if (result == IntPtr.Zero)
            throw new ApplicationException("Error getting TreeNode state.");
        var imageIndex = (tvi.state & TVIS_STATEIMAGEMASK) >> 12;
        return (imageIndex != 0);
    }
    /// <summary>
    /// Sets a value indicating if the checkbox is visible on the tree node.
    /// </summary>
    /// <param name="node">The tree node.</param>
    /// <param name="value"><value>true</value> to make the checkbox visible on the tree node; otherwise <value>false</value>.</param>
    public static void SetIsCheckBoxVisible(this TreeNode node, bool value)
    {
        if (node == null)
            throw new ArgumentNullException("node");
        if (node.TreeView == null)
            throw new InvalidOperationException("The node does not belong to a tree.");
        var tvi = new TVITEM
            {
                hItem = node.Handle,
                mask = TVIF_STATE,
                stateMask = TVIS_STATEIMAGEMASK,
                state = (value ? node.Checked ? 2 : 1 : 0) << 12
            };
        var result = SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
        if (result == IntPtr.Zero)
            throw new ApplicationException("Error setting TreeNode state.");
    }
    private const int TVIF_STATE = 0x8;
    private const int TVIS_STATEIMAGEMASK = 0xF000;
    private const int TV_FIRST = 0x1100;
    private const int TVM_GETITEM = TV_FIRST + 62;
    private const int TVM_SETITEM = TV_FIRST + 63;
    [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
    private struct TVITEM
    {
        public int mask;
        public IntPtr hItem;
        public int state;
        public int stateMask;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpszText;
        public int cchTextMax;
        public int iImage;
        public int iSelectedImage;
        public int cChildren;
        public IntPtr lParam;
    }
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam);
}