簡體   English   中英

TreeView刪除某些節點的復選框

[英]TreeView Remove CheckBox by some Nodes

我想刪除Node.Type為5或6的CheckBoxes。我使用以下代碼:

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

問題在於圖像和到根節點的線不存在。 如何刪除復選框,然后將圖像和線條放在那里?

這是錯的!

在顯示的代碼中,您將自己處理所有類型為5或6的節點的圖形。對於其余類型,您僅允許系統以默認方式繪制節點。 這就是為什么它們都具有預期的線條,但是您要繪制所有者的線條卻沒有:您忘記畫線了! 您會看到,說e.DrawDefault = false; 假設您確實是真的。 沒有完成任何常規圖紙,包括標准線。

您要么需要自己繪制這些線條,要么想出如何完全不用主人畫畫的方式。

從您現在擁有的代碼來看,您似乎正在嘗試在所有者繪圖代碼中盡可能地模擬系統的本機繪圖樣式,所以我不清楚您最初通過所有者繪圖來完成什么工作。 如果您只是嘗試不顯示類型5和6節點的復選框(像線條一樣,因為您沒有繪制它們,它們就不會被繪制!),有一種更簡單的方法可以在不涉及所有者的情況下進行畫畫。


那么,您問,隱藏單個節點復選框的最簡單方法是什么? 好吧,事實證明TreeView控件本身實際上支持此功能,但是.NET Framework中未公開該功能。 您需要P / Invoke並調用Windows API來實現。 將以下代碼添加到表單類中(確保已為System.Runtime.InteropServices添加了using聲明):

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

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

這是非常好的! 我唯一要進行的修改是僅將TreeNode而不是TreeView傳遞給HideCheckBox方法。 可以從TreeNode本身檢索TreeView

TreeView tvw = node.TreeView;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM