树形结构添加删除节点

1.树形控件的通知消息

树形控件的通知消息有很多, 
TVN_SELCHANGING和TVN_SELCHANGED:在用户改变了对树节点的选择时,控件会发送这两个消息。消息会附带一个指向NMTREEVIEW结构的指针,程序可从该结构中获得必要的信息。两个消息都会在该结构的itemOld成员中包含原来的选择项信息,在itemNew成员中包含新选择项的信息,在action成员中表明是用户的什么行为触发了该通知消息(若是TVC_BYKEYBOARD则表明是键盘,若是TVC_BYMOUSE则表明是鼠标,若是TVC_UNKNOWN则表示未知)。两个消息的不同之处在于,如果TVN_SELCHANGING的消息处理函数返回TRUE,那么就阻止选择的改变,如果返回FALSE,则允许改变。

TVN_KEYDOWN:该消息表明了一个键盘事件。消息会附带一个指向NMTVKEYDOWN结构的指针,通过该结构程序可以获得按键的信息。

TVN_BEGINLABELEDIT和TVN_ENDLABELEDIT:分别在用户开始编辑和结束编辑节点的标签时发送。消息会附带一个指向NMTVDISPINFO结构的指针,程序可从该结构中获得必要的信息。在前者的消息处理函数中,可以调用GetEditControl()成员函数返回一个指向用于编辑标题的编辑框的指针。如果处理函数返回FALSE,则允许编辑,如果返回TRUE,则禁止编辑。在后者的消息处理函数中,NMTVDISPINFO结构中的item.pszText指向编辑后的新标题,如果pszText为NULL,那么说明用户放弃了编辑,否则,程序应负责更新节点的标签,这可以由SetItem()或SetItemText()函数来完成。

2.树形控件的相关数据结构

  1. NMTREEVIEW结构体 
    NMTREEVIEW结构体中包含了树形控件通知消息的相关信息。树形控件的大多数通知消息都会带有指向该结构体的指针。NMTREEVIEW结构体的定义如下:
typedef struct tagNMTREEVIEW {   
    NMHDR hdr;      // 标准的NMHDR结构   
    UINT action;    // 表明是用户的什么行为触发了该通知消息   
    TVITEM itemOld; // 原节点的属性   
    TVITEM itemNew; // 新节点的属性   
    POINT ptDrag;   // 事件发生时鼠标的客户区坐标   
} NMTREEVIEW, *LPNMTREEVIEW;  

TVINSERTSTRUCT结构体

  1. 向树形控件中插入新节点时需要用到TVINSERTSTRUCT结构体,它常与TVM_INSERTITEM消息一起使用。定义如下:
typedef struct tagTVINSERTSTRUCT {   
    HTREEITEM hParent;      // 父节点的句柄   
    HTREEITEM hInsertAfter; // 指明插入到同层中哪一项的后面   
#if (_WIN32_IE >= 0x0400)   
    union  
    {   
        TVITEMEX itemex;   
        TVITEM item;   
    } DUMMYUNIONNAME;   
#else   
    TVITEM item;            // 要添加的新节点的属性   
#endif   
} TVINSERTSTRUCT, *LPTVINSERTSTRUCT;  

若hParent成员为TVI_ROOT或NULL,那么新节点将被作为树的根节点插入。hInsertAfter除了可以是某个节点的句柄,还可以有四种取值:TVI_FIRST(插入到树形控件的最前面)、TVI_LAST(插入到树形控件的最后面)、TVI_ROOT(作为根节点插入)和TVI_SORT(按字母顺序插入)。

3.树形控件的应用实例

树形控件的属性:

TVS_DISABLEDRAGDROP:禁止树形控件发送TVN_BEGINDRAG通知消息,即不支持拖动操作 
TVS_EDITLABELS:用户可以编辑节点的标签文本 
TVS_HASBUTTONS:显示带有"+"或"-"的小方框来表示某项能否被展开或已展开 
TVS_HASLINES:在父节点与子节点间连线以更清晰地显示树的结构 
TVS_LINESATROOT:在根节点处连线 
TVS_SHOWSELALWAYS:即使控件失去输入焦点,仍显示出项的选择状态

CTreeCtrl类的主要成员函数:

   CString GetItemText(HTREEITEM hItem) const;
   获取树形控件中某个指定节点的标签文本。参数hItem同上。返回值是包含标签文本的字符串。

   BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
   为树形控件中某个指定节点设置标签文本。参数hItem同上,lpszItem为包含标签文本的字符串的指针。

   HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;
   获取树形控件中某个指定节点的下一个兄弟节点。参数hItem同上。返回值是下一个兄弟节点的句柄。

   HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;
   获取树形控件中某个指定节点的上一个兄弟节点。参数hItem同上。返回值是上一个兄弟节点的句柄。

   HTREEITEM GetParentItem(HTREEITEM hItem) const;
   获取树形控件中某个指定节点的父节点。参数hItem同上。返回值是父节点的句柄。

   HTREEITEM GetRootItem( ) const;
   获取树形控件根节点的句柄。

   HTREEITEM GetSelectedItem( ) const;
   获取树形控件当前选中节点的句柄。

   BOOL DeleteAllItems( );
   删除树形控件中的所有节点。删除成功则返回TRUE,否则返回FALSE。

   BOOL DeleteItem(HTREEITEM hItem);
   删除树形控件中的某个节点。参数hItem为要删除的节点的句柄。删除成功则返回TRUE,否则返回FALSE。

   GetEditControl();     //获取当前选中结点编辑框

   HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);
   在树形控件中插入一个新节点。参数lpszItem为新节点的标签文本字符串的指针,参数nImage为新节点的图标在树形控件图像序列中的索引,参数nSelectedImage为新节点被选中时的图标在图像序列中的索引,参数hParent为插入节点的父节点的句柄,参数hInsertAfter为新节点的前一个节点的句柄,即新节点将被插入到hInsertAfter节点之后。

   BOOL SelectItem(HTREEITEM hItem);
   选中指定的树节点。参数hItem为要选择的节点的句柄。若成功则返回TRUE,否则返回FALSE。

树控件修改节点信息

1.添加一个Tree Control控件,ID设置为IDC_WEB_TREE,属性Has Buttons、Has Lines和Lines At Root都设为True,为了在鼠标划过某个节点时显示提示信息还需要将Info Tip属性设为True。 
2.为树形控件IDC_WEB_TREE添加CTreeCtrl类型的控件变量m_webTree。 
具体代码如下:

头文件:
public:
    CTreeCtrl m_webTree;
    afx_msg void OnBeginlabeleditWebTree(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnEndlabeleditWebTree(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnBnClickedOk();
    afx_msg void OnBnClickedCancel();
    BOOL IsTreeCtrlEditMessage(WPARAM KeyCode);
    HTREEITEM FindItem(HTREEITEM item,CString strText);

    CString g_sSelectStr;
源文件:
BOOL Ctree_controlDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);         // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标


    //m_imageList.Create(16, 16, ILC_COLOR, 2, 2);                      //创建图像列表
    //CBitmap bm;
    //bm.LoadBitmap(IDB_BITMAP1);                                   //载入Bitmap资源
    //m_imageList.Add(&bm, RGB(0, 0, 0));                           //添加到图像列表
    //bm.DeleteObject();
    //bm.LoadBitmap(IDB_BITMAP2);
    //m_imageList.Add(&bm, RGB(0, 0, 0));

    //m_ctlTree.SetImageList(&m_imageList,TVSIL_NORMAL); //为树形控件添加图像列表

    HTREEITEM hroot=m_webTree.InsertItem("csdn博客",1,0,TVI_ROOT);//添加一级结点
    HTREEITEM h1=m_webTree.InsertItem("移动开发",1,0,hroot);//添加二级结点
    HTREEITEM h2=m_webTree.InsertItem("WEB前端",1,0,hroot);//添加二级结点
    HTREEITEM h3=m_webTree.InsertItem("数据库",1,0,hroot);//添加二级结点
    HTREEITEM h11=m_webTree.InsertItem("ios",1,0,h1);//添加三级结点
    HTREEITEM h12=m_webTree.InsertItem("android",1,0,h1);//添加三级结点
    HTREEITEM h13=m_webTree.InsertItem("HTML",1,0,h2);//添加三级结点
    HTREEITEM h21=m_webTree.InsertItem("CSS",1,0,h2);//添加三级结点
    HTREEITEM h22=m_webTree.InsertItem("JavaScript",1,0,h2);//添加三级结点    

    m_webTree.SetBkColor(RGB(200,200,255)); //设置树形控件的背景色
    m_webTree.SetTextColor(RGB(127,0,0));   //设置文本颜色
    m_webTree.Select(h11,TVGN_CARET);       //子项h11为选定项
    // TODO: 在此添加额外的初始化代码

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void Ctree_controlDlg::OnBeginlabeleditWebTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    m_webTree.GetEditControl()->LimitText(1024);  
    g_sSelectStr = m_webTree.GetItemText(m_webTree.GetSelectedItem());//得到修改前的数据
    *pResult = 0;
}
void Ctree_controlDlg::OnEndlabeleditWebTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码

    //HTREEITEM m_hInsertItem;  
    CString strName;     //修改后的数据  
    CString rootstr;
    m_webTree.GetEditControl()->GetWindowText(strName);  

    if (strName.IsEmpty())  
    {  
        MessageBox("数据项名称不能为空,请重新输入!");  
        return;  
    }  
    if (strName == g_sSelectStr)  
    {  
        return;  
    }  
    HTREEITEM hRoot = m_webTree.GetRootItem();  
    //rootstr = m_webTree.GetItemText(hRoot);  

    HTREEITEM hFind = FindItem(hRoot,strName);           
    if (hFind == NULL)  //判断输入的数据是否和其他的相同 
    {  
        char msg[64]={0};  
        sprintf(msg,"修改信息为%s,确定吗?",strName);  
        if (MessageBox(msg,"提示",MB_OKCANCEL) == IDOK)  
        {  
            CString strText;  
            m_webTree.GetEditControl()->GetWindowText(strText.GetBuffer(200),200);  
            m_webTree.SetItemText(m_webTree.GetSelectedItem(),strText);//设置编辑后的文本为结点  
            *pResult = TRUE;  

        }  
        else  //取消修改
        {  
            return;
            //m_webTree.DeleteItem(m_hInsertItem); 
        }  
    }  
    else //
    {  
            MessageBox("该数据已存在");  
            return;
            //CEdit *pEdit = m_webTree.EditLabel(m_hInsertItem);      
    }  

    *pResult = 0;
}
BOOL Ctree_controlDlg::IsTreeCtrlEditMessage(WPARAM KeyCode)   
{   
    BOOL rvalue = FALSE;   
    CWnd *pWnd = this;   
    CTreeCtrl *treectrl = (CTreeCtrl *)pWnd->GetDlgItem(IDC_WEB_TREE);   
    if(!treectrl)  //没有在修改  
    {  
        return rvalue;   
    }  
    CWnd* focus = GetFocus();  
    CEdit* edit = treectrl->GetEditControl();   
    if((CEdit *)focus == edit)   
    {  
        if (KeyCode == VK_ESCAPE)    
        {  
            edit->SendMessage(WM_UNDO,KeyCode);  //ESC撤销   
        }  
        if (KeyCode == VK_RETURN)  
        {  
            edit->SendMessage(WM_KEYDOWN,KeyCode);   //回车就执行  
        }  
        rvalue = TRUE;   
    }   
    return rvalue;  
} 

void Ctree_controlDlg::OnBnClickedOk()
{
    // TODO: 在此添加控件通知处理程序代码
    if(!IsTreeCtrlEditMessage(VK_RETURN))   
    {  
        EndDialog(IDOK);   
    }  
}


void Ctree_controlDlg::OnBnClickedCancel()
{
    // TODO: 在此添加控件通知处理程序代码
    if(!IsTreeCtrlEditMessage(VK_ESCAPE))   
    {  
        EndDialog(IDCANCEL);   
    }  
}


HTREEITEM Ctree_controlDlg::FindItem(HTREEITEM item,CString strText)  
{  
    HTREEITEM hFind;  
    if (item==NULL)  //根为空,修改数据与根数据不同
    {  
        return NULL;      
    }  
    while(item!=NULL)  //根不为空,
    {  
        if (m_webTree.GetItemText(item)==strText)  
        {  
            return item;  //
        }  
        if (m_webTree.ItemHasChildren(item))  
        {  
            item = m_webTree.GetChildItem(item);  
            hFind = FindItem(item,strText);  
            if (hFind)  
            {  
                return hFind;  
            }  
            else  
            {  
                item = m_webTree.GetNextSiblingItem(m_webTree.GetParentItem(item));  //得到兄弟姐妹节点
            }  

        }  
        else  
        {  
           item = m_webTree.GetNextSiblingItem(item);
            /* if (item == NULL)  
            {  
                return NULL;  
            } */ 
           return FindItem(item,strText); 

        }  
    }  
    return item;  
}   

void Ctree_controlDlg::OnRclickWebTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}

####树控件增删节点信息
1、第一步,既然要弹出菜单,那我们首先要建立一个菜单:在工程的资源视图里,右键单击“MyTree.rc”->"添加资源",然后选择“Menu”,点击新建。新建的菜单默认ID为IDR_MENU1,当然你可以选中菜单后在其属性中修改这个ID.
2、菜单建立好了之后,我们就简单添加几个菜单项“添加节点”,“删除节点”.
3、点击右键弹出菜单。有了菜单后,我们要为树型控件添加一个右键消息响应函数消息类型: NM_RCLICK

void Ctree_controlDlg::OnRclickWebTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
       //临时鼠标的屏幕坐标,用来弹出menu
        CPoint ScreenPt;
        GetCursorPos(&ScreenPt);

        //获取到当前鼠标选择的树节点
        m_CurTree = m_webTree.GetSelectedItem();
        if (m_CurTree != NULL)
        {
                //m_webTree.SelectItem(m_CurTree); //使右键单击的树节点被选中
                CMenu menu;
                menu.LoadMenu(IDR_MENU1);
                CMenu* pPopup = menu.GetSubMenu(0);//装载第一个子菜单,即我们菜单的第一列
                pPopup->TrackPopupMenu(TPM_LEFTALIGN, ScreenPt.x, ScreenPt.y, this);//弹出菜单
        }
        *pResult = 0;
}

void Ctree_controlDlg::Onaddnode()
{
    // TODO: 在此添加命令处理程序代码
    // HTREEITEM hCurrSel = GetSelectedItem();//获取当前选中结点
    //MessageBox("tianjiajiedian"); 
     UpdateData(FALSE);
     CString m_stredit=" ";
     HTREEITEM hNew=m_webTree.InsertItem(m_stredit,0,0,m_webTree.GetSelectedItem());
     UpdateData(TRUE);
}


void Ctree_controlDlg::Ondeletenode()
{
    // TODO: 在此添加命令处理程序代码
    m_webTree.DeleteItem(m_webTree.GetSelectedItem());//删除活动的结点

}

参考: 
1.http://www.jizhuomi.com/software/200.html 
2.http://blog.csdn.net/lxh1230119/article/details/7756372 
3.http://blog.sina.com.cn/s/blog_7f66d4ea0100sie7.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值