树形控件的通知消息有很多,
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()函数来完成。
typedef struct tagNMTREEVIEW {
NMHDR hdr; // 标准的NMHDR结构
UINT action; // 表明是用户的什么行为触发了该通知消息
TVITEM itemOld; // 原节点的属性
TVITEM itemNew; // 新节点的属性
POINT ptDrag; // 事件发生时鼠标的客户区坐标
} NMTREEVIEW, *LPNMTREEVIEW;
TVINSERTSTRUCT结构体
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(按字母顺序插入)。
TVS_DISABLEDRAGDROP:禁止树形控件发送TVN_BEGINDRAG通知消息,即不支持拖动操作
TVS_EDITLABELS:用户可以编辑节点的标签文本
TVS_HASBUTTONS:显示带有"+"或"-"的小方框来表示某项能否被展开或已展开
TVS_HASLINES:在父节点与子节点间连线以更清晰地显示树的结构
TVS_LINESATROOT:在根节点处连线
TVS_SHOWSELALWAYS:即使控件失去输入焦点,仍显示出项的选择状态
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(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(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.html