TreeView Удалить CheckBox некоторыми узлами - PullRequest
25 голосов
/ 28 января 2011

Я хочу удалить флажки, где Node.Type 5 или 6. Я использую этот код:

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

Проблема в том, что тогда изображения и линии к корневому узлу нет. Как можно снять флажок и пустить изображение и линию туда?

Это неправильно!

Ответы [ 3 ]

69 голосов
/ 28 января 2011

В показанном вами коде вы сами обрабатываете рисование для всех узлов, тип которых 5 или 6. Для остальных типов вы просто позволяете системе рисовать узлы впуть по умолчанию.Вот почему все они имеют линии, как и ожидалось, а те, которые вы рисуете у владельца, нет: вы забыли нарисовать линии!Видите ли, когда вы говорите e.DrawDefault = false;, предполагается, что вы действительно это имеете в виду.Ничего из обычного рисования не выполняется, включая стандартные линии.

Вам нужно будет либо сами нарисовать эти линии, либо придумать, как вообще обойтись без рисования владельцем.

Из кода, который у вас есть сейчас, похоже, что вы пытаетесь максимально симулировать собственный стиль рисования системы в своем коде рисования владельцем, поэтому мне неясно, что именно вы выполняете с помощью рисования владельцем в первомместо.Если вы просто пытаетесь не показывать флажки для узлов типа 5 и 6 (которые, как и линии, просто не прорисовываются, потому что вы их не рисуете!), Есть более простой способ сделать это без привлечения владельца.рисование.


Итак, вы спрашиваете, как проще прятать флажки для отдельных узлов?Что ж, получается, что сам элемент управления TreeView фактически поддерживает это, но эта функциональность не предоставляется в .NET Framework.Вам нужно P / Invoke и вызвать Windows API, чтобы получить это.Добавьте следующий код в свой класс формы (убедитесь, что вы добавили объявление using для 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);
}

Все беспорядочные элементы в верхней части - это ваши объявления P / Invoke.Вам понадобится несколько констант, структура TVITEM , которая описывает атрибуты элемента дерева, и функция SendMessage .Внизу находится функция, которую вы на самом деле будете вызывать для совершения дела (HideCheckBox).Вы просто передаете элемент управления TreeView и конкретный элемент TreeNode, из которого вы хотите удалить флажок.

Таким образом, вы можете удалить флажки с каждого из дочерних узлов, чтобы получить нечто похожее на это:

TreeView with checkmarks hidden for child nodes

16 голосов
/ 06 марта 2014

Использование TreeViewExtensions.

Образец использования:

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

Вот код ответа в качестве метода расширения, с помощью которого вы можете сделать:

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);
    }
}
5 голосов
/ 18 сентября 2012

Это очень хорошо! Единственная модификация, которую я бы сделал, - это передать только TreeNode, а не TreeView методу HideCheckBox. TreeView можно получить из самого TreeNode:

TreeView tvw = node.TreeView;
...