发一个带三态复选框的TreeView[源自sourceforge.net]
样式如下图!
这种带三态复选框的TreeView可以显示出 下级节点是否全部选中,是否有选中,在很多应用程序的开发中都可能会用到!
代码如下:
// ---------------------------------------------------------------------------------------------
#region // Copyright (c) 2004, SIL International. All Rights Reserved.
// <copyright from='2004' to='2004' company='SIL International'>
// Copyright (c) 2004, SIL International. All Rights Reserved.
//
// Distributable under the terms of either the Common Public License or the
// GNU Lesser General Public License, as specified in the LICENSING.txt file.
// </copyright>
#endregion
//
// File: TriStateTreeView.cs
// Responsibility: Eberhard Beilharz/Tim Steenwyk
//
// <remarks>
// </remarks>
// ---------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace xxx
{
/// ----------------------------------------------------------------------------------------
/// <summary>
/// A tree view with tri-state check boxes
/// </summary>
/// <remarks>
/// REVIEW: If we want to have icons in addition to the check boxes, we probably have to
/// set the icons for the check boxes in a different way. The windows tree view control
/// can have a separate image list for states.
/// </remarks>
/// ----------------------------------------------------------------------------------------
public class TriStateTreeView : TreeView
{
private System.Windows.Forms.ImageList m_TriStateImages;
private System.ComponentModel.IContainer components;
/// <summary>
/// The check state
/// </summary>
/// <remarks>The states corresponds to image index</remarks>
public enum CheckState
{
/// <summary>greyed out</summary>
GreyChecked = 0,
/// <summary>Unchecked</summary>
Unchecked = 1,
/// <summary>Checked</summary>
Checked = 2,
}
#region Redefined Win-API structs and methods
/// <summary></summary>
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct TV_HITTESTINFO
{
/// <summary>Client coordinates of the point to test.</summary>
public Point pt;
/// <summary>Variable that receives information about the results of a hit test.</summary>
public TVHit flags;
/// <summary>Handle to the item that occupies the point.</summary>
public IntPtr hItem;
}
/// <summary>Hit tests for tree view</summary>
[Flags]
public enum TVHit
{
/// <summary>In the client area, but below the last item.</summary>
NoWhere = 0x0001,
/// <summary>On the bitmap associated with an item.</summary>
OnItemIcon = 0x0002,
/// <summary>On the label (string) associated with an item.</summary>
OnItemLabel = 0x0004,
/// <summary>In the indentation associated with an item.</summary>
OnItemIndent = 0x0008,
/// <summary>On the button associated with an item.</summary>
OnItemButton = 0x0010,
/// <summary>In the area to the right of an item. </summary>
OnItemRight = 0x0020,
/// <summary>On the state icon for a tree-view item that is in a user-defined state.</summary>
OnItemStateIcon = 0x0040,
/// <summary>On the bitmap or label associated with an item. </summary>
OnItem = (OnItemIcon | OnItemLabel | OnItemStateIcon),
/// <summary>Above the client area. </summary>
Above = 0x0100,
/// <summary>Below the client area.</summary>
Below = 0x0200,
/// <summary>To the right of the client area.</summary>
ToRight = 0x0400,
/// <summary>To the left of the client area.</summary>
ToLeft = 0x0800
}
/// <summary></summary>
public enum TreeViewMessages
{
/// <summary></summary>
TV_FIRST = 0x1100, // TreeView messages
/// <summary></summary>
TVM_HITTEST = (TV_FIRST + 17),
}
/// <summary></summary>
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, TreeViewMessages msg, int wParam, ref TV_HITTESTINFO lParam);
#endregion
#region Constructor and destructor
/// ------------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="TriStateTreeView"/> class.
/// </summary>
/// ------------------------------------------------------------------------------------
public TriStateTreeView()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
ImageList = m_TriStateImages;
ImageIndex = (int)CheckState.Unchecked;
SelectedImageIndex = (int)CheckState.Unchecked;
}
/// -----------------------------------------------------------------------------------
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged
/// resources; <c>false</c> to release only unmanaged resources.
/// </param>
/// -----------------------------------------------------------------------------------
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Component Designer generated code
/// -----------------------------------------------------------------------------------
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
/// -----------------------------------------------------------------------------------
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(TriStateTreeView));
this.m_TriStateImages = new System.Windows.Forms.ImageList(this.components);
//
// m_TriStateImages
//
this.m_TriStateImages.ImageSize = new System.Drawing.Size(16, 16);
this.m_TriStateImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("m_TriStateImages.ImageStream")));
this.m_TriStateImages.TransparentColor = System.Drawing.Color.Magenta;
}
#endregion
#region Overrides
/// ------------------------------------------------------------------------------------
/// <summary>
/// Called when the user clicks on an item
/// </summary>
/// <param name="e"></param>
/// ------------------------------------------------------------------------------------
protected override void OnClick(EventArgs e)
{
base.OnClick (e);
TV_HITTESTINFO hitTestInfo = new TV_HITTESTINFO();
hitTestInfo.pt = PointToClient(Control.MousePosition);
SendMessage(Handle, TreeViewMessages.TVM_HITTEST,
0, ref hitTestInfo);
if ((hitTestInfo.flags & TVHit.OnItemIcon) == TVHit.OnItemIcon)
{
TreeNode node = GetNodeAt(hitTestInfo.pt);
if (node != null)
ChangeNodeState(node);
}
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Toggle item if user presses space bar
/// </summary>
/// <param name="e"></param>
/// ------------------------------------------------------------------------------------
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown (e);
if (e.KeyCode == Keys.Space)
{
ChangeNodeState(SelectedNode);
}
}
#endregion
#region Private methods
/// ------------------------------------------------------------------------------------
/// <summary>
/// Checks or unchecks all children
/// </summary>
/// <param name="node"></param>
/// <param name="state"></param>
/// ------------------------------------------------------------------------------------
private void CheckNode(TreeNode node, CheckState state)
{
node.ImageIndex = (int)state;
node.SelectedImageIndex = (int)state;
foreach (TreeNode child in node.Nodes)
CheckNode(child, state);
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Called after a node changed its state. Has to go through all direct children and
/// set state based on children's state.
/// </summary>
/// <param name="node">Parent node</param>
/// ------------------------------------------------------------------------------------
private void ChangeParent(TreeNode node)
{
if (node == null)
return;
CheckState state = GetChecked(node.FirstNode);
foreach (TreeNode child in node.Nodes)
state &= GetChecked(child);
InternalSetChecked(node, state);
ChangeParent(node.Parent);
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Handles changing the state of a node
/// </summary>
/// <param name="node"></param>
/// ------------------------------------------------------------------------------------
private void ChangeNodeState(TreeNode node)
{
BeginUpdate();
CheckState newState;
if (node.ImageIndex == (int)CheckState.Unchecked || node.ImageIndex < 0)
newState = CheckState.Checked;
else
newState = CheckState.Unchecked;
CheckNode(node, newState);
ChangeParent(node.Parent);
EndUpdate();
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Sets the checked state of a node, but doesn't deal with children or parents
/// </summary>
/// <param name="node">Node</param>
/// <param name="state">The new checked state</param>
/// ------------------------------------------------------------------------------------
private void InternalSetChecked(TreeNode node, CheckState state)
{
node.ImageIndex = (int)state;
node.SelectedImageIndex = (int)state;
}
#endregion
#region Public methods
/// ------------------------------------------------------------------------------------
/// <summary>
/// Gets the checked state of a node
/// </summary>
/// <param name="node">Node</param>
/// <returns>The checked state</returns>
/// ------------------------------------------------------------------------------------
public CheckState GetChecked(TreeNode node)
{
if (node.ImageIndex < 0)
return CheckState.Unchecked;
else
return (CheckState)node.ImageIndex;
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Sets the checked state of a node
/// </summary>
/// <param name="node">Node</param>
/// <param name="state">The new checked state</param>
/// ------------------------------------------------------------------------------------
public void SetChecked(TreeNode node, CheckState state)
{
InternalSetChecked(node, state);
CheckNode(node, state);
ChangeParent(node.Parent);
}
#endregion
}
}
#region // Copyright (c) 2004, SIL International. All Rights Reserved.
// <copyright from='2004' to='2004' company='SIL International'>
// Copyright (c) 2004, SIL International. All Rights Reserved.
//
// Distributable under the terms of either the Common Public License or the
// GNU Lesser General Public License, as specified in the LICENSING.txt file.
// </copyright>
#endregion
//
// File: TriStateTreeView.cs
// Responsibility: Eberhard Beilharz/Tim Steenwyk
//
// <remarks>
// </remarks>
// ---------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace xxx
{
/// ----------------------------------------------------------------------------------------
/// <summary>
/// A tree view with tri-state check boxes
/// </summary>
/// <remarks>
/// REVIEW: If we want to have icons in addition to the check boxes, we probably have to
/// set the icons for the check boxes in a different way. The windows tree view control
/// can have a separate image list for states.
/// </remarks>
/// ----------------------------------------------------------------------------------------
public class TriStateTreeView : TreeView
{
private System.Windows.Forms.ImageList m_TriStateImages;
private System.ComponentModel.IContainer components;
/// <summary>
/// The check state
/// </summary>
/// <remarks>The states corresponds to image index</remarks>
public enum CheckState
{
/// <summary>greyed out</summary>
GreyChecked = 0,
/// <summary>Unchecked</summary>
Unchecked = 1,
/// <summary>Checked</summary>
Checked = 2,
}
#region Redefined Win-API structs and methods
/// <summary></summary>
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct TV_HITTESTINFO
{
/// <summary>Client coordinates of the point to test.</summary>
public Point pt;
/// <summary>Variable that receives information about the results of a hit test.</summary>
public TVHit flags;
/// <summary>Handle to the item that occupies the point.</summary>
public IntPtr hItem;
}
/// <summary>Hit tests for tree view</summary>
[Flags]
public enum TVHit
{
/// <summary>In the client area, but below the last item.</summary>
NoWhere = 0x0001,
/// <summary>On the bitmap associated with an item.</summary>
OnItemIcon = 0x0002,
/// <summary>On the label (string) associated with an item.</summary>
OnItemLabel = 0x0004,
/// <summary>In the indentation associated with an item.</summary>
OnItemIndent = 0x0008,
/// <summary>On the button associated with an item.</summary>
OnItemButton = 0x0010,
/// <summary>In the area to the right of an item. </summary>
OnItemRight = 0x0020,
/// <summary>On the state icon for a tree-view item that is in a user-defined state.</summary>
OnItemStateIcon = 0x0040,
/// <summary>On the bitmap or label associated with an item. </summary>
OnItem = (OnItemIcon | OnItemLabel | OnItemStateIcon),
/// <summary>Above the client area. </summary>
Above = 0x0100,
/// <summary>Below the client area.</summary>
Below = 0x0200,
/// <summary>To the right of the client area.</summary>
ToRight = 0x0400,
/// <summary>To the left of the client area.</summary>
ToLeft = 0x0800
}
/// <summary></summary>
public enum TreeViewMessages
{
/// <summary></summary>
TV_FIRST = 0x1100, // TreeView messages
/// <summary></summary>
TVM_HITTEST = (TV_FIRST + 17),
}
/// <summary></summary>
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, TreeViewMessages msg, int wParam, ref TV_HITTESTINFO lParam);
#endregion
#region Constructor and destructor
/// ------------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="TriStateTreeView"/> class.
/// </summary>
/// ------------------------------------------------------------------------------------
public TriStateTreeView()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
ImageList = m_TriStateImages;
ImageIndex = (int)CheckState.Unchecked;
SelectedImageIndex = (int)CheckState.Unchecked;
}
/// -----------------------------------------------------------------------------------
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged
/// resources; <c>false</c> to release only unmanaged resources.
/// </param>
/// -----------------------------------------------------------------------------------
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Component Designer generated code
/// -----------------------------------------------------------------------------------
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
/// -----------------------------------------------------------------------------------
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(TriStateTreeView));
this.m_TriStateImages = new System.Windows.Forms.ImageList(this.components);
//
// m_TriStateImages
//
this.m_TriStateImages.ImageSize = new System.Drawing.Size(16, 16);
this.m_TriStateImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("m_TriStateImages.ImageStream")));
this.m_TriStateImages.TransparentColor = System.Drawing.Color.Magenta;
}
#endregion
#region Overrides
/// ------------------------------------------------------------------------------------
/// <summary>
/// Called when the user clicks on an item
/// </summary>
/// <param name="e"></param>
/// ------------------------------------------------------------------------------------
protected override void OnClick(EventArgs e)
{
base.OnClick (e);
TV_HITTESTINFO hitTestInfo = new TV_HITTESTINFO();
hitTestInfo.pt = PointToClient(Control.MousePosition);
SendMessage(Handle, TreeViewMessages.TVM_HITTEST,
0, ref hitTestInfo);
if ((hitTestInfo.flags & TVHit.OnItemIcon) == TVHit.OnItemIcon)
{
TreeNode node = GetNodeAt(hitTestInfo.pt);
if (node != null)
ChangeNodeState(node);
}
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Toggle item if user presses space bar
/// </summary>
/// <param name="e"></param>
/// ------------------------------------------------------------------------------------
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown (e);
if (e.KeyCode == Keys.Space)
{
ChangeNodeState(SelectedNode);
}
}
#endregion
#region Private methods
/// ------------------------------------------------------------------------------------
/// <summary>
/// Checks or unchecks all children
/// </summary>
/// <param name="node"></param>
/// <param name="state"></param>
/// ------------------------------------------------------------------------------------
private void CheckNode(TreeNode node, CheckState state)
{
node.ImageIndex = (int)state;
node.SelectedImageIndex = (int)state;
foreach (TreeNode child in node.Nodes)
CheckNode(child, state);
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Called after a node changed its state. Has to go through all direct children and
/// set state based on children's state.
/// </summary>
/// <param name="node">Parent node</param>
/// ------------------------------------------------------------------------------------
private void ChangeParent(TreeNode node)
{
if (node == null)
return;
CheckState state = GetChecked(node.FirstNode);
foreach (TreeNode child in node.Nodes)
state &= GetChecked(child);
InternalSetChecked(node, state);
ChangeParent(node.Parent);
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Handles changing the state of a node
/// </summary>
/// <param name="node"></param>
/// ------------------------------------------------------------------------------------
private void ChangeNodeState(TreeNode node)
{
BeginUpdate();
CheckState newState;
if (node.ImageIndex == (int)CheckState.Unchecked || node.ImageIndex < 0)
newState = CheckState.Checked;
else
newState = CheckState.Unchecked;
CheckNode(node, newState);
ChangeParent(node.Parent);
EndUpdate();
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Sets the checked state of a node, but doesn't deal with children or parents
/// </summary>
/// <param name="node">Node</param>
/// <param name="state">The new checked state</param>
/// ------------------------------------------------------------------------------------
private void InternalSetChecked(TreeNode node, CheckState state)
{
node.ImageIndex = (int)state;
node.SelectedImageIndex = (int)state;
}
#endregion
#region Public methods
/// ------------------------------------------------------------------------------------
/// <summary>
/// Gets the checked state of a node
/// </summary>
/// <param name="node">Node</param>
/// <returns>The checked state</returns>
/// ------------------------------------------------------------------------------------
public CheckState GetChecked(TreeNode node)
{
if (node.ImageIndex < 0)
return CheckState.Unchecked;
else
return (CheckState)node.ImageIndex;
}
/// ------------------------------------------------------------------------------------
/// <summary>
/// Sets the checked state of a node
/// </summary>
/// <param name="node">Node</param>
/// <param name="state">The new checked state</param>
/// ------------------------------------------------------------------------------------
public void SetChecked(TreeNode node, CheckState state)
{
InternalSetChecked(node, state);
CheckNode(node, state);
ChangeParent(node.Parent);
}
#endregion
}
}
代码下载