如何禁用WinForms .NET中TreeView的文本选中高亮效果
解决WinForms自定义TreeView节点文本高亮问题(无需所有者绘制)
要移除鼠标点击节点时的文本高亮,且不使用所有者绘制模式,可通过以下两种简单方式实现:
方法1:设置控件为不可选中
直接禁用控件的选中能力,从根源上避免高亮行为。在自定义TreeView的构造函数中添加一行代码:
public CustomTreeView() { // 原有代码保持不变 this.HideSelection = false; this.ItemHeight = 30; // 添加这行代码,禁用控件选中能力 SetStyle(ControlStyles.Selectable, false); }
设置ControlStyles.Selectable为false后,TreeView将无法获得焦点,也不会触发任何选中相关的视觉反馈,包括鼠标点击时的文本高亮。
方法2:拦截鼠标点击文本区域的事件
如果需要保留控件的选中能力(虽然你的代码里已经通过OnBeforeSelect取消了选中),可以在OnMouseDown中判断点击区域,当点击文本区域时阻止基类处理事件,避免高亮:
修改OnMouseDown方法:
protected override void OnMouseDown(MouseEventArgs e) { TreeViewHitTestInfo hitTestInfo = HitTest(e.Location); if (hitTestInfo.Location == TreeViewHitTestLocations.Image) { // 原有图片点击处理逻辑不变 TreeNode node = hitTestInfo.Node; if (node != null) { int currentState = GetEffectiveState(node); if (currentState == 1) { SetNodeChecked(node, false); } else { SetNodeChecked(node, true); } UpdateStateIndices(node); } } // 点击文本区域时,不调用基类方法,避免触发高亮 else if (hitTestInfo.Location != TreeViewHitTestLocations.Text) { base.OnMouseDown(e); } }
这样只有点击图片区域时执行你的逻辑,点击文本区域时不会触发基类的鼠标按下处理,也就不会出现文本高亮。
完整修改后的代码
以下是整合了方法1的完整自定义TreeView代码:
public class CustomTreeView : TreeView { // 自定义复选框图片字段 private Image _checkedImage = Properties.Resources.CheckIcon; private Image _uncheckedImage = Properties.Resources.UnCheckIcon; private Image _intermediateImage = Properties.Resources.IntermediateCheckIcon; private ImageList _imageList; public CustomTreeView() { this.CheckBoxes = false; _imageList = new ImageList(); _imageList.ImageSize = new Size(26, 26); _imageList.Images.Add("Unchecked", _uncheckedImage); _imageList.Images.Add("Checked", _checkedImage); _imageList.Images.Add("Intermediate", _intermediateImage); this.ImageList = _imageList; this.Font = new Font("Gadugi", 12f); this.ForeColor = Color.DodgerBlue; this.BackColor = SystemColors.Control; this.BorderStyle = BorderStyle.None; this.Scrollable = true; this.ShowLines = false; this.ShowRootLines = false; this.ShowNodeToolTips = true; this.ShowPlusMinus = false; this.HideSelection = false; this.ItemHeight = 30; // 添加禁用选中的样式 SetStyle(ControlStyles.Selectable, false); } private int GetEffectiveState(TreeNode node) { if (node.Nodes.Count == 0) { return node.Checked ? 1 : 0; } else { bool allChecked = true; bool anyChecked = false; foreach (TreeNode child in node.Nodes) { int childState = GetEffectiveState(child); if (childState == 0) allChecked = false; else if (childState == 1) anyChecked = true; else { allChecked = false; anyChecked = true; } } if (allChecked) return 1; else if (anyChecked) return 2; else return 0; } } private void UpdateStateImageIndex(TreeNode node) { node.ImageIndex = GetEffectiveState(node); node.SelectedImageIndex = node.ImageIndex; } private void SetNodeChecked(TreeNode node, bool checkedState) { node.Checked = checkedState; foreach (TreeNode child in node.Nodes) { SetNodeChecked(child, checkedState); } } private void UpdateStateIndices(TreeNode node) { while (node != null) { UpdateStateImageIndex(node); node = node.Parent; } } protected override void OnMouseDown(MouseEventArgs e) { TreeViewHitTestInfo hitTestInfo = HitTest(e.Location); if (hitTestInfo.Location == TreeViewHitTestLocations.Image) { TreeNode node = hitTestInfo.Node; if (node != null) { int currentState = GetEffectiveState(node); if (currentState == 1) { SetNodeChecked(node, false); } else { SetNodeChecked(node, true); } UpdateStateIndices(node); } } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); TreeViewHitTestInfo hitTestInfo = HitTest(e.Location); if (hitTestInfo.Location == TreeViewHitTestLocations.Image) { this.Cursor = Cursors.Hand; } else { this.Cursor = Cursors.Default; } } protected override void OnAfterCheck(TreeViewEventArgs e) { base.OnAfterCheck(e); UpdateStateIndices(e.Node); } private void UpdateStateIndicesRecursive(TreeNode node) { node.Expand(); foreach (TreeNode child in node.Nodes) { UpdateStateIndicesRecursive(child); } UpdateStateImageIndex(node); } public void UpdateAllStateIndices() { foreach (TreeNode node in this.Nodes) { UpdateStateIndicesRecursive(node); } } protected override void OnBeforeCollapse(TreeViewCancelEventArgs e) { e.Cancel = true; } protected override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right) { e.Handled = true; } base.OnKeyDown(e); } protected override void OnBeforeSelect(TreeViewCancelEventArgs e) { e.Cancel = true; base.OnBeforeSelect(e); } }
内容的提问来源于stack exchange,提问作者Jamie Head
相关产品推荐
相关产品推荐

