How to disable a WinForms TreeView node checkbox?

倾然丶 夕夏残阳落幕 提交于 2019-11-27 01:58:12

Since there's support in C++ we can resolve it using p/invoke.

Here's the setup for the p/invoke part, just make it available to the calling class.

    // 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;

    } 

We want to determine on a node by node basis. The easiest way to do that is on the draw node event. We have to set our tree to be set as owner drawn in order for this event, so be sure to set that to something other than the default setting.

this.tree.DrawMode = TreeViewDrawMode.OwnerDrawText;
this.tree.DrawNode += new DrawTreeNodeEventHandler(tree_DrawNode);

In your tree_DrawNode function determine if the node being drawn is supposed to have a checkbox, and hide it when approriate. Then set the Default Draw property to true since we don't want to worry about drawing all the other details.

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);
    }
}

Lastly, the actual call to the function we defined:

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);
}

TreeView.BeforeCheck -- register for this event, check whether the node is one where the checkboxes are allowed to be checked or not and, if it cannot be checked then you can cancel the event by setting the Cancel property on the TreeViewCancelEventArgs. That should hopefully prevent the user from checking those boxes but will not make for the best user-experience.

To remove the checkboxes for the non-checkable items, you could possibly use owner-draw to draw a solid rectangle over the check-box to remove it.

There is nothing inbuilt to do this. You can use the BeforeCheck event and cancel it for the desired nodes. In case the appearance of the checkbox matters, then you will need to place a image there to show the checkbox disabled.

This link might be of your interest.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!