我用以下解决方案来显示或隐藏在一个TreeView复选框:的WinForms TreeView控件:检查是否复选框被隐藏
https://stackoverflow.com/a/22230299/1583649
不过,现在我想知道如何检查,如果该复选框隐藏或不为节点。
例如,我希望能够将checkbox.checked设置为true(或false),只有当顶层节点被选中时,复选框可见的顶级节点的子节点。有没有办法做到这一点?
我用以下解决方案来显示或隐藏在一个TreeView复选框:的WinForms TreeView控件:检查是否复选框被隐藏
https://stackoverflow.com/a/22230299/1583649
不过,现在我想知道如何检查,如果该复选框隐藏或不为节点。
例如,我希望能够将checkbox.checked设置为true(或false),只有当顶层节点被选中时,复选框可见的顶级节点的子节点。有没有办法做到这一点?
可以使用TVM_GETITEM或TVM_GETITEMSTATE来获取状态,然后可以使用该状态来推断节点上的哪个复选框图像(none,checked或unchecked)。这里有一个扩展类,它提供了你需要的两种方法。
用法:
// 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);
}
谢谢!很棒! – MaxOvrdrv
这些都不是必要的。只需使用TreeNode.StateImageIndex属性即可。将其设置为-1以隐藏假复选框,将其设置为0或1以选择其中一个状态图像。读回来当然也是微不足道的。 –
等待你是否说我不需要用户Interop来隐藏复选框本身? – MaxOvrdrv
我试了你的答案汉斯,它根本没有工作...对不起。 – MaxOvrdrv