C# TreeView通过某些节点删除复选框
我想删除节点类型为5或6的复选框。我使用以下代码:C# TreeView通过某些节点删除复选框,c#,winforms,checkbox,treeview,ownerdrawn,C#,Winforms,Checkbox,Treeview,Ownerdrawn,我想删除节点类型为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.S
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并调用windowsapi来获得它。将以下代码添加到表单类中(确保已使用System.Runtime.InteropServices
声明添加了):
private const int TVIF_STATE=0x8;
私有常量int TVIS_stateMageMask=0xF000;
private const int TV_FIRST=0x1100;
私用const int TVM_SETITEM=TV_FIRST+63;
[StructLayout(LayoutKind.Sequential,Pack=8,CharSet=CharSet.Auto)]
私有结构项
{
公共int掩码;
公共IntPtr hItem;
公共国家;
公共int状态掩码;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串lpszText;
公共int cchTextMax;
公共国际形象;
公共int选择图像;
公共儿童;
公共IntPtr LPRAM;
}
[DllImport(“user32.dll”,CharSet=CharSet.Auto)]
私有静态外部IntPtr SendMessage(IntPtr hWnd、int Msg、IntPtr wParam、,
参考tvram);
///
///隐藏TreeView控件上指定节点的复选框。
///
私有void HideCheckBox(TreeView tvw,TreeNode节点)
{
TviItem tvi=新的TviItem();
tvi.hItem=node.Handle;
tvi.mask=TVIF_状态;
tvi.stateMask=TVIS_stateMask;
tvi.state=0;
发送消息(tvw.Handle、TVM_设置项、IntPtr.Zero、参考tvi);
}
顶部所有凌乱的东西都是p/Invoke声明。您需要一些常量,用于描述treeview项的属性的,以及。底部是实际调用以执行契约的函数(HideCheckBox
)。只需传入TreeView
控件和要从中删除复选标记的特定TreeNode
项
因此,您可以删除每个子节点的复选标记,以获得如下内容:
这太好了!我要做的唯一修改是只将TreeNode
而不是TreeView
传递给HideCheckBox
方法。TreeView
可以从TreeNode
本身检索:
TreeView tvw = node.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);
}
}
公共静态类TreeViewExtensions
{
私有常量int TVIF_STATE=0x8;
私有常量int TVIS_stateMageMask=0xF000;
private const int TV_FIRST=0x1100;
私用const int TVM_SETITEM=TV_FIRST+63;
[StructLayout(LayoutKind.Sequential,Pack=8,CharSet=CharSet.Auto)]
私有结构项
{
公共int掩码;
公共IntPtr hItem;
公共国家;
公共int状态掩码;
[Marshallas(UnmanagedType.LPTStr)]
公共字符串lpszText;
公共int cchTextMax;
公共国际形象;
公共int选择图像;
公共儿童;
公共IntPtr LPRAM;
}
[DllImport(“user32.dll”,CharSet=CharSet.Auto)]
私有静态外部IntPtr SendMessage(IntPtr hWnd、int Msg、IntPtr wParam、,
参考tvram);
///
///隐藏TreeView控件上指定节点的复选框。
///
公共静态void HideCheckBox(此树节点)
{
TviItem tvi=新的TviItem();
tvi.hItem=node.Handle;
tvi.mask=TVIF_状态;
tvi.stateMask=TVIS_stateMask;
tvi.state=0;
SendMessage(node.TreeView.Handle,TVM_SETITEM,IntPtr.Zero,ref tvi);
}
}
我同意Hans的观点,可能存在重复;业主提款通常非常困难。如果你坚持的话,我找到了一个更完整的由所有者绘制的树状视图样本作为答案,包括节点线。@狼人:嗯,也许我错说了“更简单”。我个人认为它更简单,因为我更熟悉它,因为业主图纸很难正确绘制。基本上,TreeView
控件本身支持隐藏单个节点的复选框,但该功能在.NET Framework中没有公开。您需要P/Invoke来获得它。如果你愿意,我会用codez更新我的答案。@Charith:是的,超越所有者绘制(你肯定不想这样做,因为这涉及到工作,而且因为它永远不会像本地TreeView控件那样/表现完全一样),t
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);
}
}