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); //获得第二个子节点
}
}