如何禁用WinForms TreeView节点复选框?

Vas*_*kov 18 treeview treenode winforms

我需要能够禁用WinForms应用程序的TreeView控件中的一些复选框,但是标准TreeView控件没有内置这样的功能.

我已经在使用TreeView.BeforeCheck事件并取消它,如果该节点被禁用并且完全正常.

我还将禁用节点的ForeColor更改为GrayText.

有没有人有一个简单而强大的解决方案?

Sam*_*ost 33

由于C++中有支持,我们可以使用p/invoke来解决它.

这是p/invoke部分的设置,只是让它可供调用类使用.

    // constants used to hide a checkbox
    public const int TVIF_STATE = 0x8;
    public const int TVIS_STATEIMAGEMASK = 0xF000;
    public const int TV_FIRST = 0x1100;
    public const int TVM_SETITEM = TV_FIRST + 63;

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
    IntPtr lParam); 

    // struct used to set node properties
    public 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;

    } 
Run Code Online (Sandbox Code Playgroud)

我们希望逐个节点地确定.最简单的方法是绘制节点事件.我们必须将树设置为为此事件绘制的所有者,因此请务必将其设置为默认设置以外的其他值.

this.tree.DrawMode = TreeViewDrawMode.OwnerDrawText;
this.tree.DrawNode += new DrawTreeNodeEventHandler(tree_DrawNode);
Run Code Online (Sandbox Code Playgroud)

在您的tree_DrawNode函数中,确定正在绘制的节点是否应该有一个复选框,并在适​​当时隐藏它.然后将Default Draw属性设置为true,因为我们不想担心绘制所有其他细节.

void tree_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
    if (e.Node.Level == 1)
    {
        HideCheckBox(e.Node);
        e.DrawDefault = true;
    }
    else 
    {
        e.Graphics.DrawString(e.Node.Text, e.Node.TreeView.Font,
           Brushes.Black, e.Node.Bounds.X, e.Node.Bounds.Y);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,实际调用我们定义的函数:

private void HideCheckBox(TreeNode node)
{
    TVITEM tvi = new TVITEM();
    tvi.hItem = node.Handle;
    tvi.mask = TVIF_STATE;
    tvi.stateMask = TVIS_STATEIMAGEMASK;
    tvi.state = 0;
    IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(tvi));
    Marshal.StructureToPtr(tvi, lparam, false);
    SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, lparam);
}
Run Code Online (Sandbox Code Playgroud)

  • 在HideCheckBox函数中,将tvi.state = 0更改为tvi.state = 1 << 12.有关状态掩码的说明,请参见MSDN:http://msdn.microsoft.com/en-us/library/bb760017( VS.85)的.aspx (3认同)
  • 当我尝试此操作时,复选框最终会在实际具有复选框的节点上被切断。 (2认同)
  • 对于未来的读者:我刚刚找到了第二个问题的答案,正如 Shane Courtrille 在 2011 年发现的那样,如果将 e.DrawDefault 设置为 true,出于某种原因,Windows 在绘制文本时会删除部分复选框。实际上,我发现始终调用 DrawString() 更容易(永远不要将 e.DrawDefault 设置为 true)。 (2认同)