MFC树形控件

1.创建基于对话框的MFC.exe程序.

2.需要15个导入图标ICON,以及对话框画面,如图:这里写图片描述这里写图片描述这里写图片描述

图标名分别为这里写图片描述
这些插入的图标可自定义为你自己喜欢的,插入随便一个也可满足,就是显示的树型控件都是同一张图标而已。

3.在Dlg自定义函数中添加图像列表关联语句,并且添加树型控件的项。
需要知道树形控件的项结构:
3.1与列表控件差不多也有两个结构分别代表主项和子项,不一样的地方在于主项和子项合并在一起而是依赖于一个叫hParent和索引号去将成员连接,并且可分多层项。而列表控件只有主和子这一层。

typedef struct tagTVINSERTSTRUCTA {
    HTREEITEM hParent;//用于指定自己为哪个项的子项TV,NULL或者TVI_ROOT表示根节点
    HTREEITEM hInsertAfter;//用于指定插入项的方式,TVI_FIRST头插、TVI_LAST尾插、TVI_SORT按字母顺序插入
#if (_WIN32_IE >= 0x0400)
    union
    {
        TVITEMEXA itemex;//I don't know
        TV_ITEMA  item;//I don't know
    } DUMMYUNIONNAME;
#else
    TV_ITEMA item;//插入项的相关消息属性,是TVITEM的对象(在下面介绍)
#endif
} TVINSERTSTRUCTA, FAR *LPTVINSERTSTRUCTA;
typedef struct tagTVITEMA {
    UINT      mask;//掩码,用来指定TV_ITEM中哪些成员有效
    HTREEITEM hItem;//项目句柄
    UINT      state;//项目状态
    UINT      stateMask;//项目有效的屏蔽位
    LPSTR     pszText;//项目名称
    int       cchTextMax;//项目名称最大长度
    int       iImage;//未被选择时的图标
    int       iSelectedImage;//被选择时的图标
    int       cChildren;//该项目是否包含子项
    LPARAM    lParam;//程序定义的32位参数(每项都必须不一样,具有唯一性)
} TVITEMA, FAR *LPTVITEMA;

3.2加入树型控件 IDC_TREE 设置属性Has button、Has Lines、 Edit Labels、Lines at root,成员变量为m_cTree
3.3代码操作:

    // TODO: Add extra initialization here
    CTreeControlApp * pApp=(CTreeControlApp *)AfxGetApp();
    m_ImageList.Create(16,16,ILC_COLOR32,1,1);
    m_ImageList.Add(pApp->LoadIcon(IDI_DESKTOP));//0
    m_ImageList.Add(pApp->LoadIcon(IDI_MYDOCUMENTS));//1
    m_ImageList.Add(pApp->LoadIcon(IDI_MYPICTURE));//2
    m_ImageList.Add(pApp->LoadIcon(IDI_MYVIDEO));//3
    m_ImageList.Add(pApp->LoadIcon(IDI_MYSHAPE));//4
    m_ImageList.Add(pApp->LoadIcon(IDI_MYMUSIC));//5
    m_ImageList.Add(pApp->LoadIcon(IDI_MYCOMPUTER));//6
    m_ImageList.Add(pApp->LoadIcon(IDI_HARDDISK));//7
    m_ImageList.Add(pApp->LoadIcon(IDI_CDROMDRIVER));//8
    m_ImageList.Add(pApp->LoadIcon(IDI_FOLDERCLOSE));//9
    m_ImageList.Add(pApp->LoadIcon(IDI_FOLDEROPEN));//10
    m_ImageList.Add(pApp->LoadIcon(IDI_NETWORKNEIGHBORHOOD));//11
    m_ImageList.Add(pApp->LoadIcon(IDI_ENTIRENETWORK));//12
    m_ImageList.Add(pApp->LoadIcon(IDI_MSN));//13
    m_ImageList.Add(pApp->LoadIcon(IDI_RECYLE));//14
    m_cTree.SetImageList(&m_ImageList,TVSIL_NORMAL);//设置图像列表
    m_cTree.SetItemHeight(20);//设置高度
    TV_INSERTSTRUCT tvInsert;//定义插入项
    HTREEITEM hItemRoot,hItemSub;//定义项目
    int iParam=0;
    tvInsert.hParent=TVI_ROOT;//桌面为根节点
    tvInsert.hInsertAfter=TVI_LAST;//尾插
    tvInsert.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//掩码表示可设置的属性
    tvInsert.item.iImage=0;//未被选中的图标显示 
    tvInsert.item.iSelectedImage=0;//被选择时的图标显示
    tvInsert.item.pszText="桌面";//名字
    tvInsert.item.lParam=iParam++;//项相关参数 (唯一)
    m_cTree.InsertItem(&tvInsert);//插入操作
    tvInsert.hParent=TVI_ROOT;
    tvInsert.item.pszText="我的文档";
    tvInsert.item.iImage=1;
    tvInsert.item.iSelectedImage=1;
    tvInsert.item.lParam=iParam++;
    hItemRoot=m_cTree.InsertItem(&tvInsert);//插入后返回该项索引号,让它的子项认这个索引号就跟着它了.
    tvInsert.hParent=hItemRoot;//子项认父,父亲为上一个“我的文档”
    tvInsert.item.pszText="图片收藏";
    tvInsert.item.iImage=2;
    tvInsert.item.iSelectedImage=2;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.item.pszText="我的视频";
    tvInsert.item.iImage=3;
    tvInsert.item.iSelectedImage=3;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.item.pszText="我的形状";
    tvInsert.item.iImage=4;
    tvInsert.item.iSelectedImage=4;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.item.pszText="我的音乐";
    tvInsert.item.iImage=5;
    tvInsert.item.iSelectedImage=5;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.hParent=TVI_ROOT;//当需要插入的是根结点的时候,要重新定义hParent的值,不然还是跟在“我的文档”下面
    tvInsert.item.pszText="我的电脑";
    tvInsert.item.iImage=6;
    tvInsert.item.iSelectedImage=6;
    tvInsert.item.lParam=iParam++;
    hItemRoot=m_cTree.InsertItem(&tvInsert);
    //用数组结构方式插入
    char * partition[4]={"系统(C:)","数据(D:)","娱乐(E:)","DVC/CD-ROM驱动器(F:)"};
    char * Folder[4][5]={
        {"Documents and Settings","Program Files","WINDOWS","",""},
        {"Data","Ghost","教学","下载","资料"},
        {"movie","图片","音乐","",""},
        {"","","","",""}};
    int i,j;
    for(i=0;i<4;i++)//表示要插入4个“我的电脑”子项分别为partition[]内容
    {
        tvInsert.hParent=hItemRoot;//认“我的电脑”为父
        tvInsert.item.pszText=partition[i];
        tvInsert.item.lParam=iParam++;
        //用if else作有选择性的图标选择,0,1,27图标,38图标显示
        if(i<3)
        {
            tvInsert.item.iImage=7;
            tvInsert.item.iSelectedImage=7;
        }
        else
        {
            tvInsert.item.iImage=8;
            tvInsert.item.iSelectedImage=8;
        }
        hItemSub=m_cTree.InsertItem(&tvInsert);//“我的电脑”的子项的索引号,用于再下一层次的认父操作.
        //处理该子项的子项Folder[][]插入操作
        for(j=0;j<5;j++)
        {
            if(Folder[i][j]=="")
                break;
            tvInsert.hParent=hItemSub;//认父操作
            tvInsert.item.lParam=iParam++;
            tvInsert.item.pszText=Folder[i][j];
            tvInsert.item.iImage=9;
            tvInsert.item.iSelectedImage=10;
            m_cTree.InsertItem(&tvInsert);
        }
    }
    //后面同理
    tvInsert.hParent=TVI_ROOT;
    tvInsert.item.pszText="网上邻居";
    tvInsert.item.iImage=11;
    tvInsert.item.iSelectedImage=11;
    tvInsert.item.lParam=iParam++;
    hItemRoot=m_cTree.InsertItem(&tvInsert);
    tvInsert.hParent=hItemRoot;
    tvInsert.item.pszText="整个网络";
    tvInsert.item.iImage=12;
    tvInsert.item.iSelectedImage=12;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.item.pszText="MSN上的[我的网络]";
    tvInsert.item.iImage=13;
    tvInsert.item.iSelectedImage=13;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);
    tvInsert.hParent=TVI_ROOT;
    tvInsert.item.pszText="回收站";
    tvInsert.item.iImage=14;
    tvInsert.item.iSelectedImage=14;
    tvInsert.item.lParam=iParam++;
    m_cTree.InsertItem(&tvInsert);

3.4
增加4个按钮”添加”IDC_BTNADD
”删除“IDC_BTN_DEL
“查看”IDC_BTNVIEW
“关闭”IDOK
代码分别为:

void CTreeControlDlg::OnBtnadd() 
{
    // TODO: Add your control notification handler code here
    HTREEITEM hSel=m_cTree.GetSelectedItem();//获得选择项句柄(索引号)
    if(hSel==NULL) return ;
    static int nAddNo=100;//表示lParam项相关参数起始位置为100,防止和前面的lParam重复而定义的数
    TV_INSERTSTRUCT tvInsert;//插入项的结构体
    tvInsert.hParent=hSel;
    tvInsert.hInsertAfter=TVI_LAST;//定义插入方式,尾插
    tvInsert.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//设置掩码
    tvInsert.item.pszText="New";
    tvInsert.item.lParam=nAddNo++;
    tvInsert.item.iImage=9;//默认插入的是文件图标
    tvInsert.item.iSelectedImage=10;//被选择时的图标
    HTREEITEM hInsert=m_cTree.InsertItem(&tvInsert);
    m_cTree.Expand(hSel,TVE_EXPAND);//展开被选择项 (也有折叠功能)
    m_cTree.EditLabel(hInsert);//修改插入项时的焦点集中作用,即进行修改中状态
}

实现EditLable功能,即实现修改项目名称的功能还需要一些处理,若不进行处理,当修改完项目的名称后,还会恢复原先的值。这是因为程序中没有对修改结果进行保存。利用TV_DISPINFO结构和SetItemText函数对TVN_ENDLABELEDIT进行处理就可以正确实现修改功能。
TVN_ENDLABELEDIT消息是在用户修改完一个项目后发送的。

大白话来说就是:你只是把修改的内容打上去了,但还没有按回车,所以还未真正修改成功。而这个ENDLABELEDIT操作就是一个”回车”的作用,不过要注意:你在这个程序里面按回车是处理ONOK函数即退出对话框操作,EditLabel作用是选中要修改的项,并进入(正在修改中)状态
在这里我们可以想到如果想要用快捷键回车来处理“回车”操作的话,那就需要一个快捷键了。

void CTreeControlDlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
    TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
    //pTVDispInfo 可理解为修改的项
    // TODO: Add your control notification handler code here
    if(pTVDispInfo->item.pszText==0)return ;//用户输入的是0的话就退出修改操作
    m_cTree.SetItemText(pTVDispInfo->item.hItem,pTVDispInfo->item.pszText);//设置新数据,hItem是项目句柄,用于识别修改的项,
    *pResult = 0;
}

删除操作:

void CTreeControlDlg::OnBtnDel() 
{
    // TODO: Add your control notification handler code here
    HTREEITEM hSel=m_cTree.GetSelectedItem();//获取选项句柄
    if(hSel==NULL)return ;
    if(m_cTree.ItemHasChildren(hSel))//删除的项是否有子项函数,有就返回1,否则返回0
        if(MessageBox("是否连同其子项一起删除?","确认",MB_ICONQUESTION|MB_YESNO)!=IDYES)return ;
        m_cTree.DeleteItem(hSel);//用索引号删除该项
}

查看操作函数:


void CTreeControlDlg::OnBtnview() 
{
    // TODO: Add your control notification handler code here
    HTREEITEM hSel=m_cTree.GetSelectedItem();//获取被选择项的索引号
    if(hSel==NULL)return;
    CString cText=m_cTree.GetItemText(hSel);//获取项目名称
    LONG Data=m_cTree.GetItemData(hSel);//获取项目编号 lParam
    char temp[100];
    wsprintf(temp,"目录:%s 编号:%05d",cText,Data);
    MessageBox(temp,"信息");
}

运行开始

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值