求重写TreeView的CheckBoxes实现第三种状态(有部分子节点选中)
我在参考了这里,确实实现了第三种状态,但是点击某行的任意位置都会触发该节点状态改变,所以不想用这种方法。现希望各位大虾给出通过重写TreeView的办法来实现当部分子结点被选中时父节点有第三种状态的详细代码。
[解决办法]
示例代码在5楼:
http://topic.csdn.net/u/20080529/18/304A8BE8-F534-4CC4-921E-BD9E3E9E1969.html
[解决办法]
/// <summary> /// 获取某个节点的状态。 /// </summary> /// <param name="node">要获取状态的节点</param> /// <returns>当前节点的状态</returns> //*********************************************************** //* 函数名称:GetChecked //* 功能描述:获取当前节点的状态 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** public EnumCheckState GetChecked(TreeNode node) { TVITEM tTVITEM = new TVITEM(); int iState; int iResult; tTVITEM.mask = (int)(TVHit.OnItemButton | TVHit.OnItemIndent); tTVITEM.hItem = node.Handle; tTVITEM.stateMask = (int)(TVHit.TVIS_STATEIMAGEMASK); tTVITEM.state = 0; iResult = SendMessage(this.Handle, TreeViewMessages.TVM_GETITEM, 0, ref tTVITEM); if (iResult != 0) { iState = tTVITEM.state; iState = iState / 0xFFF; return (EnumCheckState)(iState); } else { return EnumCheckState.Unchecked; } } /// <summary> /// 设置节点状态。 /// </summary> /// <param name="node">要设置的节点</param> /// <param name="state">设置的状态</param> //*********************************************************** //* 函数名称:SetChecked //* 功能描述:设置节点的状态 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** public void SetChecked(TreeNode node, EnumCheckState state) { CheckNode(node, state); if (m_bThreeState && !m_bRadioCheck) { ChangeParent(node.Parent); } } /// <summary> /// 设置一个节点的状态,且当前节点的父节点和子节点状态不改变。 /// </summary> /// <param name="node">要设置的节点</param> /// <param name="state">设置的状态</param> //*********************************************************** //* 函数名称:SetInternalChecked //* 功能描述:改变当前节点的状态 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** public void SetInternalChecked(TreeNode node, EnumCheckState state) { int iState = (int)state; TVITEM tTVITEM = new TVITEM(); tTVITEM.mask = (int)(TVHit.OnItemButton | TVHit.OnItemIndent); tTVITEM.hItem = node.Handle; tTVITEM.stateMask = (int)TVHit.TVIS_STATEIMAGEMASK; tTVITEM.state = iState * 0x1000; SendMessage(this.Handle, TreeViewMessages.TVM_SETITEM, 0, ref tTVITEM); base.OnAfterCheck(new System.Windows.Forms.TreeViewEventArgs(node)); } #endregion #region "重写方法" /// <summary> /// 重写控件的 Refresh 方法,重绘控件 /// </summary> //*********************************************************** //* 函数名称:Refresh //* 功能描述:重写Refresh方法 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** public override void Refresh() { SetStateImageList(null); if (m_bOnlyLeavesCheckBox && this.Nodes.Count > 0) { SetParentCheckBoxStateNone(this.Nodes); } else { // foreach(TreeNode node in this.Nodes) // { // if(node.Nodes.Count>0) // SetParentCheckBoxStateNotNone(node); // } } base.Refresh(); } /// <summary> /// 重写控件的 OnParentChanged 方法,重绘控件 /// </summary> //*********************************************************** //* 函数名称:OnParentChanged //* 功能描述:重写OnParentChanged方法 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** protected override void OnParentChanged(EventArgs e) { Refresh(); base.OnParentChanged(e); } /// <summary> /// 重写控件的 OnClick 方法,判断鼠标位置是否在状态图标内,如果在,则改变节点状态。 /// </summary> //*********************************************************** //* 函数名称:OnClick //* 功能描述:重写单击事件,判断鼠标单击位置 //* 参 数:无 //* 返 回 值: //* 作 者: //* 创建日期:2004-06-28 //*********************************************************** protected override void OnClick(System.EventArgs e) { Point pt = PointToClient(Control.MousePosition); base.OnClick(e); if (m_bReadOnly || m_bCancel) { return; } TreeNode node = GetTreeNodeHitAtCheckBoxByClientPosition(pt.X, pt.Y); if (node != null) { ChangeNodeState(node); } } /// <summary> /// 重写控件的 OnVisibleChanged 方法,重绘控件 /// </summary> protected override void OnVisibleChanged(EventArgs e) { if (this.Visible) Refresh(); base.OnVisibleChanged(e); } /// <summary> /// 重写控件的 OnMouseDown 方法,鼠标右键选中节点 /// </summary> protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Right && m_bSelectNodeAtRButtonMouseDownOneNode) { TreeNode node = this.GetNodeAt(e.X, e.Y); if (node != null) this.SelectedNode = node; } base.OnMouseDown(e); }