通俗弄清楚TreeView写注册表编辑器

希望和2天前的我一样或对于TreeView尚处于迷忙中的朋友来说,送去一点亮光。

让我们继续出发吧!!!

TreeView
通俗的把我对TreeView的理解和大家分享。
都知道它是树型结构,是由一层一层的节点(TreeNode)构成,其中根节点(RootNode)、子节点(SubNode)、更低层的其它节点(OtherNode),大概就是上述结构。
我们常常见到的TreeView型的实例就很多了,像注册表编辑器、资源管理器等。
下面以前者为例来具体写。
RootNode:HKEY_CLASSES_ROOT
SubNode1:*
SubNode2:OpenWithList
OtherNode:Excel.exe、IExplore.exe、MSPaint.exe、Notepad.exe、Winword.exe、WordPad.exe
附图:reg1

这里我一开始比较难理解的是它的事件
因为从书上网上看到其中最重要的几个事件有:
AfterCollapse、AfterExpand、AfterSelect、BeforeCollapse、BeforeExpand、BeforeSelect

在这里要使用的是BeforeExpand事件,书上说的比较含糊,个人感觉少说了一些,结果造成新手在使用上不是很熟悉。
个人感觉步骤是这样的,比如要对
对HKEY_CLASSES_ROOT添加子项OpenWithList
对OpenWithList添加子项Excel.exe、IExplore.exe、MSPaint.exe、Notepad.exe、Winword.exe、WordPad.exe
添加的方法:
public void rootNodes()
{
 tvRegistry.BeginUpdate();
 //先创建RootNode tnHKCR
 TreeNode tnHKCR = new TreeNode("HKEY_CLASSES_ROOT",0,1);
 //再添加到TreeView tvRegistry
 tvRegistry.Nodes.add(tnHKCR);
 //有了以后再向根节点tnHKCR添加系统设置的下层节点
 addBranch(tnHKCR);
 //其它节点类似
 tvRegistry.SelectedNode = tnHKLM;
 tvRegistry.EndUpdate();
}
以上在程序运行时,就立刻加载了一个HKEY_CLASSES_ROOT节点,并且几乎同时加载了系统配置的HKEY_CLASSES_ROOT节点的若干子节点,在这里举例*、._sln、._sln60、._sln70、._sln71、._sln80……
这里只是举了若干,实际上非常多。
在没有执行BeforeExpand事件之前,也就加载到这里,这时HKEY_CLASSES_ROOT的前面有一个加号('+'),我们不讨论点击使其展开后情况,这时表明HKEY_CLASSES_ROOT的配置子节点已经加载完毕,由于刚开始就是程序运行而已,所以不可能发生BeforeExpand事件,所以再下一层的节点群eg OpenWithList、shellex等 此时还没有加载,但配置是确定的,那是系统的事情,和我们这里不相关,更别说OpenWithList的下一层节点群了


FullPath获取全路径判断是那个分支,这里明显是HKEY_CLASSES_ROOT,一眼就看出来了,MessageBox.Show(strRegistryPath);显示HKEY_CLASSES_ROOT
StartsWith("HKEY_CLASSES_ROOT")判断是否是以字符串HKEY_CLASSES_ROOT开头,这里是的,所以if条件为true,执行regBranch = Registry.ClassesRoot;注册分支,第二个MessageBox.Show(regBranch.ToString());测试过了,显示的还是HKEY_CLASSES_ROOT,当父节点
HKEY_CLASSES_ROOT时,tn.Parent == null,执行的是else语句,直接赋值regSubKey = regBranch;,类型均为RegistryKey。
regSubKey.GetSubKeyNames();获取HKEY_CLASSES_ROOT的系统配置的子节点群,结果返回的是string数组,我们就是要用他们,把他们加载到目前HKEY_CLASSES_ROOT上面,用for循环 string[].length,然后string[][i],i从0到string[].length-1;
TreeNode tnBranch = new TreeNode(string[][i],0,1);
HKEY_CLASSES_ROOT.Nodes.Add(tnBranch);
这样把所有该有的节点群,都加载到了该加载的地方。
其它的父根节点和它都是一样的,至于和本代码一样写1个方法,只是优化的问题,当前不再讨论之内。

至此已经完成了父节点和他的子节点群的加载,那么怎样实现我们一点击某个分支,如HKEY_CLASSES_ROOT
它下面的分支就展开,并且如果系统配置了再下一层节点的话我们照样实现加载呢?
刚才说过了,程序在以运行时,只是加载了诸如HKEY_CLASSES_ROOT等(一般为5个分支),和HKEY_CLASSES_ROOT下一层的节点群,再往下就没有了,只是显示一个个的文件夹,前面并没有加号('+')了,但此时我们并看不到到底有没有加号,只有当我们点击了其中之一时,如HKEY_CLASSES_ROOT,HKEY_CLASSES_ROOT的下一层算是真正打开了,*等显示了出来(很多很多),此时我们可是真正看到了有些是有加号的,有些则没有。没有的那就说明配置上本身就没有,有的则说明本身配置是有的。
和以前一样,要在此时将有加号的('+')节点加载配置,但此时程序已经开始运行一段时间了,情况不一样了,那么就涉及到BeforeExpand事件的问题了。
这里有个很重要的地方,就是e.Node.Nodes,个人认为,这样理解就可以,那就是e点击HKEY_CLASSES_ROOT 的事件,e.Node确定了发生点击事件的节点,这里就为HKEY_CLASSES_ROOT,当点击的稍微还提前一些的时候,即已经点击过了,这时这段很少的事件,可能只有0.000几秒,要分好几段了,首先一点击HKEY_CLASSES_ROOT 就要展开,即expand,但我们还没看到真正的展开时,这个阶段太重要了,加载HKEY_CLASSES_ROOT 下一层如*,再下一层OpenWithList就已经完成了,但OpenWithList的下一层并没有被加载,明白我说的话?
然后才是我们看到的真正的展开了HKEY_CLASSES_ROOT ,我们看到了*等等节点群,有的如*是有加号的,有的没有,有的就已经加载了。
没有的就到此为止。
e.Node.Nodes确定了HKEY_CLASSES_ROOT的下一层,*等等节点,由于e.Node.Nodes是在一开始就已经加载好的,所以e.Node.Nodes是固定的,已经有了内容的。用tvRegistry.BeginUpdate();
            foreach (TreeNode tn in e.Node.Nodes)
            {
                AddBranch(tn);
            }
            tvRegistry.EndUpdate();
foreach循环给配置还有下一层的加载节点群,如给*等加载节点群 OpenWithList、shellex,一直把所有的河*同层的节点加载完为止。
由于是*层,所以tn.FullPath的MessageBox.Show(strRegistryPath);显示HKEY_CLASSES_ROOT/* 等,其它类推,strRegistryPath.StartsWith("HKEY_CLASSES_ROOT")为true,执行regBranch = Registry.ClassesRoot;,因为此时不是根节点,null != tn.Parent,所以执行if条件语句,int nPosPathSeparator = strRegistryPath.IndexOf(this.tvRegistry.PathSeparator);从HKEY_CLASSES_ROOT/*,众找'/'路径分隔符号索引号,this.tvRegistry.PathSeparator表示是找这个路径分隔符号,而且是第一个,
这里显示17,然后+1,string strSubkey = strRegistryPath.Substring(nPosPathSeparator+1);获取子节点的string,这里是*,
是string类型,然后regSubKey = regBranch.OpenSubKey(strSubkey);,找到*节点string对应的RegisterKey regSubKey 就是*,这里是和父节点不一样的地方。
然后还是一样的
string[] astrSubkeyNames = regSubKey.GetSubKeyNames();
   for (int i=0; i < astrSubkeyNames.Length; i++)
   {
    TreeNode tnBranch = new TreeNode(astrSubkeyNames[i],0,1);
    tn.Nodes.Add(tnBranch);
   }
获取regSubKey.GetSubKeyNames(),就是获取*等的下层节点群 OpenWithList、shellex,返回string数组,还是foreach循环,创建节点并添加到*上,tn.Nodes.Add(tnBranch);,tn就是*,Nodes属性后调用节点添加方法Add,一次添加一个配置节点,SubTreeNode。
这里是完成了3个层次,再往下的话情况是完全一样的,BeforeExpand事件巧妙的处理的这里,设计的真是太棒了,让我们对设计者们致敬。

public void AddBranch(TreeNode tn)
{
 tn.Nodes.Clear();
   string strRegistryPath = tn.FullPath;
            MessageBox.Show(strRegistryPath);

   RegistryKey regBranch = null;
            if (strRegistryPath.StartsWith("HKEY_CLASSES_ROOT"))
                regBranch = Registry.ClassesRoot;
            else if (strRegistryPath.StartsWith("HKEY_CURRENT_USER"))
                regBranch = Registry.CurrentUser;
            else if (strRegistryPath.StartsWith("HKEY_LOCAL_MACHINE"))
                regBranch = Registry.LocalMachine;
            else if (strRegistryPath.StartsWith("HKEY_USERS"))
                regBranch = Registry.Users;

            MessageBox.Show(regBranch.ToString());

   RegistryKey regSubKey = null;
   try
   {
    if (null != tn.Parent)
    {
     // we need the path minus the top level tree
     int nPosPathSeparator = strRegistryPath.IndexOf(this.tvRegistry.PathSeparator);
                    MessageBox.Show(nPosPathSeparator.ToString());
     string strSubkey = strRegistryPath.Substring(nPosPathSeparator+1);
                    MessageBox.Show(strSubkey.ToString());
     regSubKey = regBranch.OpenSubKey(strSubkey);
    }
    else
     regSubKey = regBranch;
   }
   catch
   {
    return;
   }

   string[] astrSubkeyNames = regSubKey.GetSubKeyNames();
   for (int i=0; i < astrSubkeyNames.Length; i++)
   {
    TreeNode tnBranch = new TreeNode(astrSubkeyNames[i],0,1);
    tn.Nodes.Add(tnBranch);
   }
}
rivate void tvRegistry_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
        {
            tvRegistry.BeginUpdate();
            foreach (TreeNode tn in e.Node.Nodes)
            {
                AddBranch(tn);
            }
            tvRegistry.EndUpdate();
        }
由于第一次写文章,图解的问题,图片没传上来,以后会补图的。
这个例子说明了BeforeExpand事件的作用,e.Node.Nodes需要我们好好理解
至于TreeView还有其它很多的事件,以后用到的时候我会以实例来说明,这样才有意义。
希望朋友们提出宝贵意见,以便我改进和做的更好,大家一起努力。

 

 


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值