树形控件在界面编程中应用十分普遍,如在资源管理器中和树形结构显示书的目录等,我们一步步研究树形控件的使用。
在对话框界面上首先拖动创建一个树,一般我们改变三个属性:
Has Buttons显示带有”+”或”-“的小方框,表示某项能否被展开或已展开,默认为选中,我们改为选中。
Has Lines在父项与子项之间连线以清楚地显示结构,默认为选中,改为选中。
Lines at root:在根部划线,默认为选中,改为选中。
其余根据需要,可以修改,如Always show slection,Edit labels
接下来就要按我们的需要显示内容了,请看常用函数:
改变节点函数:
插入树节点:HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage,int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST)
lpszItem为项的名称,nImage为位图序列的索引,nSelectedImage为选中项的位图序列索引,hParent为插入项的父项,如果为TVI_ROOT或NULL,则插入树的最高层,hInsertAfter取值为TVI_FIRST,TVI_LAST,TVI_SORT。
删除树节点:BOOL DeleteItem(HTREEITEM hItem)
删除所有树节点:BOOL DeleteAllItems()
扩展节点:BOOL Expand(HTREEITEM hItem, UINT nCode),nCode是一个标志,指定了函数执行的操作,可以是TVE_COLLAPSE(折叠),TVE_COLLAPSERESET(折叠并移走所有的子项),TVE_EXPAND(展开),TVE_TOGGLE(在展开和折叠状态之间反转).
遍历树节点相关函数:
HTREEITEM GetRootItem() const;
HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const
HTREEITEM GetChildItem(HTREEITEM hItem) const
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const
HTREEITEM GetParentItem(HTREEITEM hItem) const
HTREEITEM GetFirstVisibleItem() const
HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const
HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const
HTREEITEM GetLastVisibleItem() const
获取设置节点标题:
CString GetItemText(_In_ HTREEITEM hItem) const;
BOOL SetItemText(_In_ HTREEITEM hItem, _In_z_ LPCTSTR lpszItem);
获得或设置选择的节点:
HTREEITEM GetSelectedItem() const
BOOL SelectItem(HTREEITEM hItem)
是否有子节点:BOOL ItemHasChildren(_In_ HTREEITEM hItem) const;
检测点是否在树节点区域:HTREEITEM HitTest(_In_ CPoint pt, _In_opt_ UINT* pFlags = NULL) const;
判断是否是否最顶层节点用GetParentItem(hItem)== NULL
树节点右键单击菜单的实现,先重载右键单击函数,然后分别实现相应菜单的功能:
void C**Dlg::OnNMRClickTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此添加控件通知处理程序代码
CPoint pt;
GetCursorPos(&pt);
m_Tree.ScreenToClient(&pt);
HTREEITEM hCurItem = m_Tree.GetSelectedItem();
//判断右键的位置处是否是树形控件的一个节点
//若有,则弹出右键菜单
HTREEITEM hItem = m_Tree.HitTest(pt);
if (hItem == NULL)
{
m_Tree.SelectItem(NULL);
}
else if (hCurItem != hItem)
{
m_Tree.SelectItem(hItem);
}
m_Tree.ClientToScreen(&pt);
CMenu menu;
if (menu.LoadMenuA(IDR_MENU1))
{
CMenu* pMenu = menu.GetSubMenu(1);
if (pMenu != NULL)
{
pMenu->TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, this);
pMenu->DestroyMenu();
*pResult = 1;
return;
}
}
*pResult = 0;
}
实现树节点的多选和拖动需要派生一个新类,在此不再详写了。