• MFC应用技术之CTreeControl的使用


             MFC应用技术之CTreeControl的使用

    一丶MFC添加树控件.添加父节点跟子节点.

      MFC上面放一个树控件.并未这个树控件绑定变量.然后添加一个按钮.按钮的作用就是添加父节点跟子节点.

    PS: 关于MFC如果添加控件.这里不做讲解.此篇只用于应用.所以常用的都会列举出来.

      树控件添加结点注意用的 方法是 InsertItem()

    这个方法是重载的有很多种. 这里只讲解自己常用的一种.其余的查询MSDN即可.

    添加父节点跟子节点.

    void CTreeControlDlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
        HTREEITEM Root =  m_RootControl.InsertItem(_T("父节点"));   返回一个句柄
         m_RootControl.InsertItem(_T("子节点5"), Root,TVI_SORT);    继续调用这个方法添加的时候.参数二是父节点返回的句柄.则添加结点到父节点下面. 参数三是排序的意思.可以默认不加.
         m_RootControl.InsertItem(_T("子节点4"), Root, TVI_SORT);
         m_RootControl.InsertItem(_T("子节点3"), Root, TVI_SORT);
         m_RootControl.InsertItem(_T("子节点2"), Root, TVI_SORT);
         m_RootControl.InsertItem(_T("子节点1"), Root, TVI_SORT);
    
    }

    应用截图:

      

    二丶获取树控件父节点以及子节点

       获取树控件父节点 方法是  GetRootItem() 返回的Item句柄就是父节点. GetChildItem() 则是获取子节点.传入父节点.返回子节点.

       GetItemText(句柄)  返回这个句柄的字符串.  GetParentItem() 获取子节点的父节点. 

    看如下代码:

      

    void CTreeControlDlg::OnBnClickedButton2()
    {
        // TODO: 在此添加控件通知处理程序代码
        HTREEITEM Root = m_RootControl.GetRootItem();  //获取顶层结点.
        HTREEITEM ChildItem = m_RootControl.GetChildItem(Root);
        CString strText = m_RootControl.GetItemText(ChildItem);
        AfxMessageBox(strText);
    }

    应用截图:

      

    三丶根据根节点获取兄弟结点

      获取根节点我们知道了.就是GetRootItem(); 那么获取兄弟结点是什么意思?

    意思就是兄弟的意思.  假设我们有三个父结点.

      父结点0

      父节点1

      父节点2

    我们首先获取父节点0的Item 然后继续获取他的兄弟结点.兄弟结点就是父节点1

    方法:  GetNextSiblingItem()  获取指定结点的下一个兄弟

    方法: GetPrevSiblingItem();  获取指定结点的上一个兄弟.

    具体代码例子:

      

    void CTreeControlDlg::OnBnClickedButton3()
    {
        // TODO: 在此添加控件通知处理程序代码
        HTREEITEM Root = m_RootControl.GetRootItem();                 //获取根节点
        HTREEITEM BrothorItem = m_RootControl.GetNextSiblingItem(Root);//获取跟结点的下一个兄弟结点
    
        CString strText = m_RootControl.GetItemText(BrothorItem);      //获取兄弟结点的文本穿
        AfxMessageBox(strText);
    
    }

    应用截图:

      

    获取上一个兄弟结点

      

    void CTreeControlDlg::OnBnClickedButton4()
    {
        // TODO: 在此添加控件通知处理程序代码
        HTREEITEM Root = m_RootControl.GetRootItem();
    
        HTREEITEM BrothorItem1 = m_RootControl.GetNextSiblingItem(Root);  //获取下一个兄弟结点    这里我们要先获取下一个兄弟.因为根节点的上一个兄弟没有了.
    
        HTREEITEM BrothorItem2 = m_RootControl.GetPrevSiblingItem(BrothorItem1); //获取上一个兄弟  这里就是获取第二个节点的上一个兄弟,也就是父节点0
    
        CString strText = m_RootControl.GetItemText(BrothorItem2);
        AfxMessageBox(strText);
        
    }

    应用截图:

      

    四丶根据指定结点.递归遍历下面所有子节点.

      上面都是简单的使用. 所以真正使用我们要遍历结点. 比如遍历父节点下面的所有子节点.

    递归遍历:

      1.递归遍历指定结点下面所有的子节点

    void CTreeControlDlg::OnBnClickedButton5()
    {
        // TODO: 在此添加控件通知处理程序代码
        //1.获取根节点
        HTREEITEM RootItem = m_RootControl.GetRootItem();
        IteratorTreeChild(RootItem);
    }
    
    void CTreeControlDlg::IteratorTreeChild(HTREEITEM item)
    {
        CString strText = m_RootControl.GetItemText(item); //获取字符串.并且弹出.
        AfxMessageBox(strText);
    
        //定义两个结点.一个当前结点.一个下一个结点.
        HTREEITEM CurItem;
        HTREEITEM NextItem;
    
        CurItem = m_RootControl.GetChildItem(item); //当前结点是子节点.
        while (CurItem != NULL)
        {
            //继续遍历集结点.
            NextItem = CurItem;
            IteratorTreeChild(NextItem);
            CurItem = m_RootControl.GetNextSiblingItem(NextItem);
        }
    }

    代码只打印了. 

      1.传入根节点.

      2.定义两个结点.

      3.当前结点是子节点的Item

      4.下一个结点也是Item

      5.递归遍历.

      6.如果没有.则获取下一个子节点.也就是子节点的兄弟结点.

    实现截图:

      

    2.循环遍历指定结点下面的一层子节点

    上图是递归遍历所有子节点.但是有的时候我们只需要遍历一层即可.

     例如下图: 我们只需要遍历到子节点5.

    实现代码:

      

    void CTreeControlDlg::IteratorTreeChild2(HTREEITEM item) //循环遍历当前父节点的子节点.不深层遍历
    {
        HTREEITEM CurrItem = m_RootControl.GetChildItem(item);  // 获取子节点句柄
        CString strText;
        while (CurrItem)
        {
            strText = m_RootControl.GetItemText(CurrItem);
            AfxMessageBox(strText);
            CurrItem = m_RootControl.GetNextSiblingItem(CurrItem); //获取子节点的兄弟结点即可.
        }
    }
    
    
    void CTreeControlDlg::OnBnClickedButton6()
    {
        // TODO: 在此添加控件通知处理程序代码
        HTREEITEM RootItem = m_RootControl.GetRootItem();          //根据根节点遍历根节点下面的一层子节点.
        IteratorTreeChild2(RootItem);
    }

    3.递归遍历所有父节点下面的所有子节点

      如果我们要遍历所有父节点.跟他的子节点. 则需要稍微更改下代码即可.也就是第一种代码的改进.

    实现代码:

      

    void CTreeControlDlg::OnBnClickedButton7()  
    {
        // TODO: 在此添加控件通知处理程序代码
    
        HTREEITEM RootItem = m_RootControl.GetRootItem();
        do
        {
            IteratorTreeChild1(RootItem);                                      //递归方法是第一种里面的.所以不再重复写了
        } while ((RootItem = m_RootControl.GetNextSiblingItem(RootItem)) != NULL); //主要就是这里.循环遍历父节点的兄弟结点.
        
    }

    4.循环遍历所有父节点下的第一层子节点.

      上面的是遍历父节点下的子节点. 所有的子节点. 子节点的子节点也遍历.但是我们只需要遍历一层

    void CTreeControlDlg::OnBnClickedButton7()  
    {
        // TODO: 在此添加控件通知处理程序代码
    
        HTREEITEM RootItem = m_RootControl.GetRootItem();
        HTREEITEM CurItem; 
        CString strText;
        do
        {
            CurItem = m_RootControl.GetChildItem(RootItem);    //双层循环.第一层遍历父节点.第二层遍历子节点的兄弟结点.
            while (CurItem)
            {
                strText = m_RootControl.GetItemText(CurItem);
                AfxMessageBox(strText);
    
                CurItem = m_RootControl.GetNextSiblingItem(CurItem);
            }
            
        } while ((RootItem = m_RootControl.GetNextSiblingItem(RootItem)) != NULL);
        
    }

    常用的遍历差不多就这些了.我们看下响应时间消息

    五丶事件消息

      树控件的消息有如下.

    通知消息说明

    TVN_BEGINDRAG指示拖放操作的开始。

    TVN_BEGINLABELEDIT将通知开始就地编辑标签

    TVN_BEGINRDRAG使用鼠标右键,终止拖放操作的开始,

    TVN_DELETEITEM标志着特定中删除项

    TVN_ENDLABELEDIT信号的结束编辑标签

    TVN_GETDISPINFO请求树控件需要显示的项的信息。

    TVN_ITEMEXPANDED子项父项的列表展开或折叠的信号

    TVN_ITEMEXPANDING子项的父项列表会展开或折叠的信号

    TVN_KEYDOWN信号键盘事件

    TVN_SELCHANGE信号从中选择一项更改为另一个架构

    TVN_SELCHANGING指示选定项即将从一项变为另一项

    TVN_GETDISPINFO更新的信息通知为维护项

    具体可以查询MSDN

    MSDN 链接: https://technet.microsoft.com/zh-cn/library/38x8htxs.aspx/

     关于我们主要讲解 TVN_SELCHANGE 也就是当选择则会改变.

    如果添加事件消息.那么会有如下代码.

    void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
        // TODO: 在此添加控件通知处理程序代码
    
        
        *pResult = 0;
    }

    这个是给我们默认添加的. 而返回值是微软已经给我们转好的.所以我们需要的信息就在里面.我们可以看下结构内容.

    LPNMTREEVIEW 这是一个宏.宽版本还是A版本. 熟悉Windows的都应该知道.
    看下对应的结构
    typedef struct tagNMTREEVIEWW {
        NMHDR       hdr;
        UINT        action;
        TVITEMW    itemOld;    旧的Item
        TVITEMW    itemNew;    当前点击的Item
        POINT       ptDrag;    坐标
    } NMTREEVIEWW, *LPNMTREEVIEWW;

    里面有一个新的结构体.也就是 TVITEMW

    看下这个结构里面内容.

    typedef struct tagTVITEMW {
        UINT      mask;
        HTREEITEM hItem;          当前的hitem结构
        UINT      state;          状态.
        UINT      stateMask;
        LPWSTR    pszText;         文本.
        int       cchTextMax;
        int       iImage;          图像
        int       iSelectedImage;  选择图形
        int       cChildren;
        LPARAM    lParam;          附加参数
    } TVITEMW, *LPTVITEMW;

    当然上面是我自己理解的然后加的注释.不过没有错误. 而我们常用的就是 hitem结构.

    所以如果我们要获取选择项的item文本就用如下代码.

    void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
        // TODO: 在此添加控件通知处理程序代码
    
        HTREEITEM Root = pNMTreeView->itemNew.hItem;
        CStringW str = m_RootControl.GetItemText(Root);
        AfxMessageBox(str);
        *pResult = 0;
    }

    或者是点击子节点.获取她的父节点.

    void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
        // TODO: 在此添加控件通知处理程序代码
    
        HTREEITEM Child = pNMTreeView->itemNew.hItem;
        HTREEITEM Root = m_RootControl.GetParentItem(Child);
        CString str = m_RootControl.GetItemText(Root);
        AfxMessageBox(str);
        *pResult = 0;
    }
     
  • 相关阅读:
    IP 封包中的 Header 的 Protocol 字段的 值
    二叉树算法题
    PageFile Swap File
    Quick sort C# code(2)
    VS中Sos调试扩展简介 (转帖)
    BUG: "Old format or invalid type library" error when automating Excel on 64 bit server 2008
    Sql server 2005 connection string
    让IE支持自己的协议
    偶然间,我发现了一个秘密能使盗版的windowsXP变成正版
    Excel C# Automation
  • 原文地址:https://www.cnblogs.com/iBinary/p/9622033.html
Copyright © 2020-2023  润新知