TreeView supprimer la case à cocher par certains noeuds

je veux enlever les cases à cocher où le noeud.Tapez 5 ou 6. J'utilise ce code:

private void TvOne_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
    int type = (e.Node as Node).typ;
    if (type == 5 || type == 6)
    {
        Color backColor, foreColor;
        if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
        {
            backColor = SystemColors.Highlight;
            foreColor = SystemColors.HighlightText;
        }
        else if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
        {
            backColor = SystemColors.HotTrack;
            foreColor = SystemColors.HighlightText;
        }
        else
        {
            backColor = e.Node.BackColor;
            foreColor = e.Node.ForeColor;
        }
        using (SolidBrush brush = new SolidBrush(backColor))
        {
            e.Graphics.FillRectangle(brush, e.Node.Bounds);
        }
        TextRenderer.DrawText(e.Graphics, e.Node.Text, this.TvOne.Font,
            e.Node.Bounds, foreColor, backColor);

        if ((e.State & TreeNodeStates.Focused) == TreeNodeStates.Focused)
        {
            ControlPaint.DrawFocusRectangle(e.Graphics, e.Node.Bounds,
                foreColor, backColor);
        }
        e.DrawDefault = false;
    }
    else
    {
        e.DrawDefault = true;
    }
}

le problème est que l'Image et la ligne vers le noeud racine ne sont pas là. Comment supprimer la case à cocher et laisser L'Image et la ligne là?

C'est faux!

23
demandé sur Deduplicator 2011-01-28 12:17:24

3 réponses

dans le code que vous avez montré, vous manipulez le dessin vous-même pour tous les noeuds dont le type est soit 5 ou 6. Pour les autres types, vous permettez simplement au système de dessiner les noeuds de la manière par défaut. C'est pourquoi ils ont tous les lignes comme prévu, mais ceux que vous êtes propriétaire-dessin ne le font pas: vous avez oublié de dessiner dans les lignes! Vous voyez, quand vous dites e.DrawDefault = false; il est supposé que vous le pensez vraiment. Aucun des réguliers dessin est fait, y compris la norme ligne.

vous aurez soit besoin de dessiner ces lignes vous-même, ou de comprendre comment se débrouiller sans propriétaire-dessin du tout.

à partir du code que vous avez maintenant, il semble que vous essayez de simuler le style de dessin natif du système autant que possible dans votre code de dessin de propriétaire, donc il n'est pas clair pour moi ce que vous accomplissez exactement par le dessin de propriétaire en premier lieu. Si vous essayez juste d'empêcher les cases à cocher d'apparaître pour les noeuds de type 5 et 6 (qui, comme les lignes, sont pas tiré parce que vous n'êtes pas de dessin!), il y a une façon plus simple de le faire sans faire appel au dessin du propriétaire.


alors, vous vous demandez, quelle est cette façon plus simple de cacher les cases à cocher pour les noeuds individuels? Eh bien, il s'avère que le TreeView le contrôle lui-même supporte cela, mais cette fonctionnalité n'est pas exposée dans le Framework .NET. Vous devez P/invoquer et appeler L'API Windows pour y accéder. Ajoutez le code suivant à votre classe de formulaire (assurez-vous que vous avez ajouté un using déclaration System.Runtime.InteropServices):

private const int TVIF_STATE = 0x8;
private const int TVIS_STATEIMAGEMASK = 0xF000;
private const int TV_FIRST = 0x1100;
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);

/// <summary>
/// Hides the checkbox for the specified node on a TreeView control.
/// </summary>
private void HideCheckBox(TreeView tvw, TreeNode node)
{
    TVITEM tvi = new TVITEM();
    tvi.hItem = node.Handle;
    tvi.mask = TVIF_STATE;
    tvi.stateMask = TVIS_STATEIMAGEMASK;
    tvi.state = 0;
    SendMessage(tvw.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
}

toutes les choses désordonnées au sommet sont vos déclarations P/Invoke. Vous avez besoin d'une poignée de constantes, l' TVITEM structure qui décrit les attributs d'un treeview élément, et le SendMessage function. En bas, il y a la fonction que vous appellerez pour faire l'acte (HideCheckBox). Vous passez simplement dans le TreeView contrôle et le particulier TreeNode article dont vous voulez supprimer coche.

vous pouvez donc enlever les crochets de chacun des noeuds enfant pour obtenir quelque chose qui ressemble à ceci:

TreeView with checkmarks hidden for child nodes

67
répondu Cody Gray 2011-01-28 10:25:27

Utilisation De TreeViewExtensions.

Utilisation exemple:

private void MyForm_Load(object sender, EventArgs e)
{
     this.treeview1.DrawMode = TreeViewDrawMode.OwnerDrawText;
     this.treeview1.DrawNode += new DrawTreeNodeEventHandler(arbolDependencias_DrawNode);
}

void treeview1_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
    if (e.Node.Level == 1) e.Node.HideCheckBox();
    e.DrawDefault = true;
}

voici le code de la réponse comme une méthode D'Extension, en utilisant ceci vous pouvez faire:

public static class TreeViewExtensions
{
    private const int TVIF_STATE = 0x8;
    private const int TVIS_STATEIMAGEMASK = 0xF000;
    private const int TV_FIRST = 0x1100;
    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);

    /// <summary>
    /// Hides the checkbox for the specified node on a TreeView control.
    /// </summary>
    public static void HideCheckBox(this TreeNode node)
    {
        TVITEM tvi = new TVITEM();
        tvi.hItem = node.Handle;
        tvi.mask = TVIF_STATE;
        tvi.stateMask = TVIS_STATEIMAGEMASK;
        tvi.state = 0;
        SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
    }
}
14
répondu user1404096 2014-11-26 12:51:56

C'est très bon! La seule modification que je ferais est de passer seulement le TreeNode et pas TreeViewHideCheckBox méthode. TreeView peut être récupéré à partir de l' TreeNode lui-même:

TreeView tvw = node.TreeView;
4
répondu user1680739 2012-09-18 19:45:20