c# winforms checkbox treeview ownerdrawn

c# - TreeView Eliminar CheckBox por algunos nodos



winforms ownerdrawn (3)

¡Esto es muy bueno! La única modificación que haría es pasar solo el TreeNode y no el TreeView al método HideCheckBox . El TreeView se puede recuperar desde el mismo TreeNode :

TreeView tvw = node.TreeView;

Quiero eliminar CheckBoxes donde el Node.Type es 5 o 6. Uso este código:

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

El problema es que entonces la imagen y la línea al nodo raíz no están allí. ¿Cómo se puede quitar la casilla de verificación y dejar que la imagen y la línea estén ahí?

¡Esto está mal!


En el código que ha mostrado, usted mismo maneja el dibujo para todos los nodos cuyo tipo es 5 o 6. Para el resto de los tipos, simplemente está permitiendo que el sistema dibuje los nodos de la forma predeterminada. Es por eso que todos tienen las líneas como se esperaba, pero las que usted es propietario de dibujar no: ¡Se olvidó de dibujar en las líneas! Verás, cuando dices e.DrawDefault = false; se asume que realmente lo dices. No se realiza ningún dibujo regular, incluidas las líneas estándar.

Tendrá que dibujar esas líneas usted mismo, o averiguar cómo sobrevivir sin dibujar propietario en absoluto.

Desde el código que tiene ahora, parece que está tratando de simular el estilo de dibujo nativo del sistema tanto como sea posible en su código de dibujo de propietario, por lo que no tengo claro qué es exactamente lo que logra exactamente con el dibujo de propietario. . Si solo intenta evitar que aparezcan las casillas de verificación de los nodos de tipo 5 y 6 (que, como las líneas, simplemente no se dibujan porque no las está dibujando), hay una forma más sencilla de hacerlo sin involucrar al propietario. dibujo.

Entonces, pregunta, ¿cuál es la forma más sencilla de ocultar las casillas de verificación de nodos individuales? Bueno, resulta que el propio control TreeView en realidad lo admite, pero esa funcionalidad no está expuesta en .NET Framework. Necesitas P / Invocar y llamar a la API de Windows para obtenerlo. Agregue el siguiente código a su clase de formulario (asegúrese de haber agregado una declaración de using para 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); }

Todas las cosas desordenadas en la parte superior son sus declaraciones P / Invoke. Necesita un puñado de constantes, la estructura TVITEM que describe los atributos de un elemento de vista de árbol y la función SendMessage . En la parte inferior está la función a la que llamarás para hacer la escritura ( HideCheckBox ). Simplemente pase el control TreeView y el elemento TreeNode particular del que desea eliminar la marca de verificación.

Por lo tanto, puede eliminar las marcas de verificación de cada uno de los nodos secundarios para obtener algo que se parece a esto:


Utilizando TreeViewExtensions.

Muestra de uso

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

Aquí está el código de la respuesta como un método de extensión, utilizando esto puede hacer:

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