c# - TreeView 通过一些节点移除 CheckBox

标签 c# winforms checkbox treeview ownerdrawn

我想删除 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;
    }
}

问题是图像和到根节点的线不存在。 如何删除复选框并让图像和线条在那里?

This is wrong!

最佳答案

在您展示的代码中,您自己处理所有类型为 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 声明。您需要一些常量,描述 TreeView 项属性的 TVITEM structureSendMessage function 。底部是执行操作时实际调用的函数 (HideCheckBox)。您只需传入 TreeView 控件和要从中删除复选标记的特定 TreeNode 项。

因此您可以从每个子节点中删除复选标记以获得如下所示的内容:

TreeView with checkmarks hidden for child nodes

关于c# - TreeView 通过一些节点移除 CheckBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4826556/

相关文章:

asp.net-mvc - MVC CheckBoxFor 导致绕过不引人注目的验证

Javascript 按顺序验证复选框

c# - 如何以编程方式设置标签页的键?

.net - 如何强制Web浏览器控件始终在同一窗口中打开网页?

c# - 将 Caliburn.Metro.Demo 从 C# 转换为 VB

c# - C#中的另一种获取属性名(这个是静态的)

c# - ("") 和 (null) 有什么区别

javascript - Bootstrap 模式停止复选框选择

c# - 错误或 Azure DevOps 错误 : TF402484 The personnel team project has been deleted

c# - 如何找出导致 NullReferenceException 的原因