共享社区

首页 » 互联网资源共享社区 » .NET源码共享 » 支持三态的TreeView控件
mikecat - 2008-9-27 8:35:00
.Net framework提供了TreeView 控件,但该控件不支持三态的形式。所谓三态就是带CheckBox的TreeView每个Node都有三种状态,即选中,未选中和部分选中(指该Node的字节点并非全部选中)。
    我做了一个支持这种功能的控件:TriStateTreeView。如下图所示:
   
    该控件支持三态的TreeView,并且支持当某个节点的Checkbox 状态发生改变时,自动回溯子节点和父节点。

    使用该控件需要注意的是,必须使用AddTreeNode方法增加Node. 不能用Nodes.Add来增加。
    该控件还提供了下面两个方法来获取和设置Node的Checkbox 状态:GetTreeNodeCheckBoxChecked,SetTreeNodeCheckBoxChecked
    当Checkbox状态发生改变时,该控件提供一个 CheckBoxStateChanged  事件来截获状态的变化。
    如果你觉得Checkbox 的图形不好看,你可以通过 CheckBoxStateImageList 属性来修改Checkbox 的图形

    下载位置: V1.0.0.4 Source Code

      关键技术:
      本控件是通过改变Node 对应的Checkbox的图形来实现三种状态显示不同的Checkbox边框的。在CheckBoxStateImageList这个ImageList中存放了4个图标,分别显示空状态,选中状态,未选中状态和部分选中状态的图形。由于TreeView控件没有封装修改CheckBox图形的方法,本控件通过向TreeView发生一个Windows消息来修改控件的图形:
      修改方法见下面代码:

/// <summary>
        /// Set tree node checkbox state
        /// </summary>
        /// <param name="treeNode">tree node</param>
        /// <param name="checkboxState">checkbox state</param>
        private void SetTreeNodeState(TreeNode treeNode, CheckBoxState checkboxState)
        {
            IntPtr hWnd;
            TVITEM tvi;
            hWnd = this.Handle;

            // Send a TVM_SETIMAGELIST with TVSIL_STATE.
            if (!_ImageListSent)
            {

                SendMessage(hWnd, (UInt32)TVM_SETIMAGELIST, (UInt32)TVSIL_STATE,

(UInt32)CheckBoxStateImageList.Handle);


                _ImageListSent = true;
            }

            // The following uses the TVM_SETITEM message to set the State
            // of a given item. It uses the TVITEM structure.

            //  tvi.mask: include TVIF_HANDLE and TVIF_STATE
            tvi.mask = TVIF_HANDLE | TVIF_STATE;

            // To use the State image, tvi.State cannot be 0. 
            //Setting it to 1 means to use the second image in the image list.
            tvi.state = (uint)checkboxState;
            // Left shift 12 to put info in bits 12 to 15
            tvi.state = tvi.state << 12;
            // Set StateMask. -This is required to isolate State above.
            tvi.stateMask = TVIS_STATEIMAGEMASK;

            // Define the item we want to set the State in.
            tvi.hItem = treeNode.Handle;  //For example, try the root.

            //  Initialize the rest to zero.
            tvi.pszText = (IntPtr)0;
            tvi.cchTextMax = 0;
            tvi.iImage = 0;
            tvi.iSelectedImage = 0;
            tvi.cChildren = 0;
            tvi.lParam = (IntPtr)0;

            // Send the TVM_SETITEM message.
            //  TVM_SETITEM = 4365
            SendMessage(hWnd, (UInt32)TVM_SETITEM, (UInt32)0, ref tvi);

            //Set Node State
            SetNodeState(treeNode, checkboxState);
        }


首先需要发送 TVM_SETIMAGELIST 通知TreeView CheckBox 使用的ImageList。然后发送 TVM_SETITEM 来设置CheckBox 对应的图形。

原文出处:http://www.cnblogs.com/eaglet
1
查看完整版本: 支持三态的TreeView控件