C# winform TreeView 屏蔽双击展开/折叠子节点

一搜索这个基本都是一样的通过事件来处理

思路:

1.通过点击事件,记录点击的节点信息(是否为双击了节点的bounds,是的话在第二步cancel掉)

2.通过BeforeExpand、BeforeCollapse事件来cancel掉

参考这个:WinForm TreeView屏蔽双击节点展开_JaremyShort的博客-CSDN博客

↑↑↑↑以上方法实现简单,不喜欢折腾的人就直接用它吧↑↑↑↑

本人有强迫症也喜欢折腾,于是看源码,查看它是怎么通过消息来实现的,果然找到了对应的实现;

我的思路是重写WndProc来拦截它。实现起来比较复杂,开工

1.首先新建一个class 继承 TreeView, override WndProc

 protected unsafe override void WndProc(ref Message m)
        {
            if (WndProcUnsafe(ref m))
            {
                return;
            }

            base.WndProc(ref m);
        }

2.需要拦截双击事件WM_LBUTTONDBLCLK、和WM_NOTIFY + WM_REFLECT

WM_LBUTTONDBLCLK:记录双击了

WM_NOTIFY + WM_REFLECT:这里是处理是否展开关闭的关键

    private unsafe bool WndProcUnsafe(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_NOTIFY + WM_REFLECT
                    when WmNotify(ref m):
                    return true;
                case WM_LBUTTONDBLCLK:
                    var node = GetNodeAt(new Point((int)m.LParam));
                    if (node.Nodes.Count > 0)//有子节点的才记录
                        _treeViewState[TREEVIEWSTATE_doubleclickFired] = true;//记录双击
                    break;
            }

            return false;
        }

private unsafe bool WmNotify(ref Message m)
        {
            var nmhdr = (NMHDR*)m.LParam;
            if ((nmhdr->code == NM_CUSTOMDRAW))//这里是自定义绘制
            {
                return false;
            }

            var nmtv = (NMTREEVIEW*)m.LParam;
            switch (nmtv->nmhdr.code)
            {
                case TVN_ITEMEXPANDINGA:
                case TVN_ITEMEXPANDINGW:
                    {
                        if (_treeViewState[TREEVIEWSTATE_doubleclickFired])//是否是双击
                        {
                            _treeViewState[TREEVIEWSTATE_doubleclickFired] = false;
                            var item = nmtv->itemNew;
                            //这里判断是否要展开或者折叠
                            if (OnBeforeExpandingEx(_getNodeByHandle(item.hItem)))
                            {
                                m.Result = (IntPtr)1;
                                return true;
                            }
                        }

                        break;
                    }
            }

            return false;
        }

实例源码请查看我的GitHub GitHub - lwinhong/TreeViewEx

你可能感兴趣的:(C#,Winform,c#,winform,treeview)