MFC控件(6):Tree Control

Tree Control顾名思义,样子自然是长的像树了,非常适合用来显示有树形结构的信息.

 

创建Tree  Control

 

静态创建

大部分时候我们都是用静态方式创建控件,因为这最简单.直接从Toolbox中拖一个控件放到Dialog中就行了.然后要以在PRoperties页面设置一些属性.如果要在代码中对控件进行操作,可以这样得到控件指针,GetDlgItem(Ctrl_ID) .如果想更灵活点可以给控件绑定一个变量.

CTreeCtrl m_treeShow;

DDX_Control(pDX, IDC_TREE1, m_treeShow);

动态创建

动态创建有两个要注意的地方.

1.怎么指定控件位置和大小. 通过CRect rect(2,2, 4,4,)这样直接的数字指定是很不灵活的,假如页面上控件一多,并且后面又想加入新控件了,会非常混乱不好维护.

比较好的一个方法是在页面上弄一个static text 或picture control,然后把它们的visiable设为false.调整好它们的位置和大小.然后获取它们的CRect作为动态创建控件的CRect.

 

2.怎么指定控件ID.动态创建时需要显式指定一个ID,我们知道ID只是一个数字.但是关键是确保同一个页面上的ID不能相同.你当然可以简单的定义一个宏.但这样不太好.一个比较简单的方法是在String Table中添加一行,用那个ID.这里不是真的需要string里面的信息,而只是这个ID.当然使用规范还是要遵守,caption里面也随便填点东西别为空.

 

 

CTreeCtrl* m_pTree;

m_pTree = new CTreeCtrl;

CRect rect;

GetDlgItem(IDC_SPACE)->GetWindowRect(&rect); //IDC_SPCE 是一个static text的ID

ScreenToClient(rect);  //屏幕坐标转化成窗口坐标,貌似不能像这样

//GetDlgItem(IDC_SPACE)->GetClientRect(rect)直接获取窗口坐标的,这样获得到位置是窗口的原点位置.

 

 

m_pTree->Create(WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_BORDER

| TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES

| TVS_DISABLEDRAGDROP | TVS_NOTOOLTipS | TVS_EDITLABELS

, rect, this, IDS_TREE);  // IDS_TREE是在string table中随便指定的一ID

 

HTREEITEM hRoot;

hRoot = m_pTree->InsertItem(_T(”china”),TVI_ROOT); //插入一个根节点

 

插入图片

界面上多整几个图标会比较好看点.那怎么往Tree Control中添加图片呢?

首先要是构造一个类CImageList,往里面添加图片,常用的图片有ico, png, bmp这三种格式.添加它们的方式有点不同

CImageList* pImgList;

pImgList = new CImageList;

pImgList -> Create(16,16, ILC_COLOR32 | ILC_MASK, 0, 1);

 

//ico图片

pImgList->Add(AfxGetApp()->LoadIconW(IDI_ICON1));

//bmp图片

CBitmap bmp;

bmp.LoadBitmapW(IDB_BITMAP1);

pImgList->Add(&bmp, RGB(0,0,0));

//png图片

CPngImage png;

png.Load(IDB_PNG1);

CBitmap pngBmp;

pngBmp.Attach(png.Detach());

pImgList->Add(&pngBmp, RGB(0,0,0));

 

//将CImageList与Tree control绑定

m_pTree-> SetImageList(pImgList, TVSIL_NORMAL); //这样一绑定,之后插入的节点如果不显式指定图标将默认使用CImageList中第一个图标

HTREEITEM hRoot;

hRoot = m_pTree->InsertItem( _T(“China”),TVI_ROOT);

m_pTree->InsertItem( _T(“China”), 1,1,hRoot, TVI_LAST) ; //显式指定pImgList中第二图标

 

插入数据

先所控件绑定到如下变量

CTreeCtrl m_treeShow;

创建一个以中国为根结点,然后一些省和城市为子结点的树形结构信息.

 

//设置树形控件样式

m_treeShow.ModifyStyle(NULL,TVS_HASBUTTONS | TVS_LINESATROOT |TVS_HASLINES);

 

//HTREEITEM相当于是一个结点的句柄

HTREEITEM hRoot;

HREEITEM hChild;

 

hRoot = m_treeShow.InsertItem( “中国”, TVI_ROOT); //插入根结点

hChild = m_treeShow.InsertItem(“湖南省”,hRoot);

hChild = m_treeShow.InsertItem(“长沙市”,hChild);

hChild = m_treeShow.InsertItem(“岳麓区”,hChild);

 

hChild = m_treeShow.InsertItem(“广东省”,hRoot);

 

删除节点

要删除节点那肯定要想办法怎么找到节点才行.

HTREEITEM hItem, hSelected;

hSelected = m_treeShow.GetSelectedItem();

m_treeShow.DeleteItem( hSelected); //删除选择的节点,如果节点下面还有子节点也会被一起删掉.

 

hItem = m_treeShow.GetRootItem(); //整棵树的根结点

hItem = m_treeShow.GetChildItem(hSelected); //获得选择节点的子节点

hItem = m_treeShow.GetParentItem(hSelected); //获得选择节点的子节点

hItem = m_treeShow.GetPrevSiblingItem(hSelected); //获得选择节点的上一兄弟结点

hItem = m_treeShow.GetNextSiblingItem(hSelected); //获得选择节点的下一兄弟结点

 

m_treeShow.DeleteAllItems(); //删除所有节点

 

展开节点

默认情况下节点都是折叠起来的.如果只展开某个结点下面一层的内容.

HTREEITEM hItem, hRoot;

hRoot = m_treeShow.GetRootItem();

m_treeShow.Expand ( hRoot, TVE_EXPAND); //只展开根结点下面一层.

 

ExpandAllNode( hRoot , m_treeShow);

那如果要展开所选结点下面所有节点咋整呢

void ExpandAllNode(HTREEITEM hItem, CTreeCtrl& m_treeShow){

HTREEITEM hChild = m_treeShow.GetChildItem(hItem); //获得第一个子节点

while(hChild){

m_treeShow.Expand(hItem,TVE_EXPAND); //展开当前节点

ExpandTreeNode(hChild, m_treeShow); //递归展开第一个子节点下所有节点

hChild = m_treeShow.GetNextSiblingItem(hChild); //获得第二个子节点

}

}