我需要能够禁用WinForms应用程序的TreeView控件中的一些复选框,但是标准TreeView控件没有内置这样的功能.
我已经在使用TreeView.BeforeCheck事件并取消它,如果该节点被禁用并且完全正常.
我还将禁用节点的ForeColor更改为GrayText.
有没有人有一个简单而强大的解决方案?
由于C++中有支持,我们可以使用p/invoke来解决它.
这是p/invoke部分的设置,只是让它可供调用类使用.
// constants used to hide a checkbox public const int TVIF_STATE = 0x8; public const int TVIS_STATEIMAGEMASK = 0xF000; public const int TV_FIRST = 0x1100; public const int TVM_SETITEM = TV_FIRST + 63; [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); // struct used to set node properties public 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; }
我们希望逐个节点地确定.最简单的方法是绘制节点事件.我们必须将树设置为为此事件绘制的所有者,因此请务必将其设置为默认设置以外的其他值.
this.tree.DrawMode = TreeViewDrawMode.OwnerDrawText; this.tree.DrawNode += new DrawTreeNodeEventHandler(tree_DrawNode);
在您的tree_DrawNode函数中,确定正在绘制的节点是否应该有一个复选框,并在适当时隐藏它.然后将Default Draw属性设置为true,因为我们不想担心绘制所有其他细节.
void tree_DrawNode(object sender, DrawTreeNodeEventArgs e) { if (e.Node.Level == 1) { HideCheckBox(e.Node); e.DrawDefault = true; } else { e.Graphics.DrawString(e.Node.Text, e.Node.TreeView.Font, Brushes.Black, e.Node.Bounds.X, e.Node.Bounds.Y); } }
最后,实际调用我们定义的函数:
private void HideCheckBox(TreeNode node) { TVITEM tvi = new TVITEM(); tvi.hItem = node.Handle; tvi.mask = TVIF_STATE; tvi.stateMask = TVIS_STATEIMAGEMASK; tvi.state = 0; IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(tvi)); Marshal.StructureToPtr(tvi, lparam, false); SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, lparam); }