树控件添加编辑框总结

来源:互联网 发布:淘宝助理批量替换图片 编辑:程序博客网 时间:2024/06/05 15:45

树控件添加编辑框总结

1》首先介绍一下树控件在树控件节点上添加编辑框以编辑节点的功能:

转自CSDN帖子http://topic.csdn.net/u/20090305/09/96ff46f8-da84-4321-9669-2efcee826a81.html

 

树控件默认的编辑框无法随意更改位置,你不如自己放置一个编辑框在树控件上,实现编辑框的移动和更改尺寸:
1.在对话框的树控件上放置一个文本框,标识符为IDC_EDIT1
向对话框类中添加三个变量:
CEdit pedit;//这个变量用于后期绑定到控件
HTREEITEM hitem;//用于追踪单击的项目句柄
BOOL bKillFocus;//表明是否失去焦点,构造函数中将其赋予False;
2.在对话框头文件中添加如下消息:
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
afx_msg void OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnEnKillfocusEdit1();
3.在对话框的Cpp文件中添加消息注册:
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CMyTreeDlgDlg::OnTvnSelchangedTree1)
ON_EN_KILLFOCUS(IDC_EDIT1, &CMyTreeDlgDlg::OnEnKillfocusEdit1)
4.在对话框的OnInitDialog中添加:
pedit.SetParent(&m_Tree);//将使得文本框显示在树控件之上。
5.添加消息体:
//当文本框中按下了Enter键,表示提交修改记录
BOOL CMyTreeDlgDlg::PreTranslateMessage(MSG* pMsg)
{
  if(pMsg->hwnd==pedit.GetSafeHwnd() && pMsg->message==WM_KEYDOWN)
{
if(pMsg->wParam==VK_RETURN)//如果用户在文本框上按下了Enter键
{
CString text;
pedit.GetWindowText(text);
m_Tree.SetItemText(hitem,text);//设置当前节点的文本
pedit.ShowWindow(SW_HIDE);//隐藏文本框

return TRUE;//阻止了父类对消息的处理,使得按下回车键时,不会关闭对话框
}

}


return CDialog::PreTranslateMessage(pMsg);
}
//当选中某个节点时,使编辑框可见,将节点文本赋给文本框
void CMyTreeDlgDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码

POINT PT;
GetCursorPos(&PT);
m_Tree.ScreenToClient(&PT);
TVHITTESTINFO hitInfo;
hitInfo.pt=PT;
  hitem=m_Tree.GetSelectedItem();
m_Tree.HitTest(&hitInfo);
if(hitInfo.flags & TVHT_ONITEMLABEL)//判断是否单击在文本上
{
CRect rect;
m_Tree.GetItemRect(hitem,&rect,TRUE);   
  

CString mes=m_Tree.GetItemText(hitem);
rect.InflateRect(0,0,0,2);//增大文本框的高度使其可以容纳整行文本。


pedit.MoveWindow(&rect,TRUE);
pedit.ShowWindow(SW_NORMAL);
pedit.SetWindowText(mes);
pedit.BringWindowToTop();
pedit.SetFocus();//使文本框聚焦

  pedit.SetSel(0,-1);//选中所有文本
    
bKillFocus=true;//设置聚集状态为True,以便在之后语句中进行判断

}

*pResult = 1;
}
//当文本框失去焦点,会将消息发送给主窗体。OnCmdMsg用于事先捕获命令消息。在这个方法设置返回值可以屏蔽掉文本框的KillFocus的消息处理流程。但是此方法不能阻止消息的发送,也就是说文本框聚焦状态还是会改变
BOOL CMyTreeDlgDlg::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(nID==IDC_EDIT1 && nCode==EN_KILLFOCUS)//判断是否是文本框发出了EN_KILLFOCUS消息
{
if(bKillFocus)//如果是由于单击树节点显示出文本框之后失去了焦点
{
bKillFocus=false;//设置聚集状态为False,阻止此方法再次调用
pedit.SetFocus();//因为文本框已失去聚焦,需要将其再次聚焦
return TRUE;//阻止了文本框KillFocus消息体的处理
}
}
return CDialog::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);
}
//将文本框失去焦点时,需要将其隐藏,然后把文本框的文本赋给当前节点
void CMyTreeDlgDlg::OnEnKillfocusEdit1()
{
// TODO: 在此添加控件通知处理程序代码
POINT pt;
  GetCursorPos(&pt);
m_Tree.ScreenToClient(&pt);
CRect rect;
m_Tree.GetItemRect(hitem,&rect,TRUE);
if(!rect.PtInRect(pt))//如果单击在一个节点文本区域内
{
CString text;
pedit.GetWindowText(text);
m_Tree.SetItemText(hitem,text);
pedit.ShowWindow(SW_HIDE);//将文本框隐藏
}

}

 

 

2》下面介绍一下如何将编辑框移动,使编辑框在节点的后面以达到美观好用的效果,浮云,一切皆是浮云;

 

tree edit

 

介绍一下我实现如图所示效果的图的步骤:

 

1:创建编辑框:

首先我们需要在每个需要画编辑框节点后面画一个编辑框,如何画请参见1》中的在节点上画编辑框的方法;

我们采取动态地画编辑框,在创建编辑框时将节点的Data值转存在编辑框中,将编辑框的句柄存储在节点的data数据之中;当然也可以自己定义结构体将编辑框的句柄和需要的data值一并存储在data数据之中;我实现的方法是前者看起来有些愚笨:

 

本人程序给出的是在第三层节点创建编辑框,而且是在展开第二层节点时在其子节点后一并创建所有编辑框操作;

2:删除编辑框:

在我们将节点展开时,我们需要 创建编辑框,但是当要将节点收缩时,我们需要将我们创建的编辑框删除,由于我们将这些节点的编辑框句柄存储在节点的数据值中,于是我们通过对这些句柄操作可以将这些编辑框删除;

 

 

3:调整编辑框:

在完成了创建,删除编辑框的操作后,我们将调整我们编辑框的变化对应与不同的事件的操作:

首先是OnTvnItemexpanded消息中我们需要在此调用我们的创建编辑框的函数

 

这里使用了GetIndentLevel()函数得到节点所处的层数:

 

 

 

也使用的ReFreshEdit()函数来及时根据我们节点的状态更新我们的编辑框存在状态:

 

这样我们在点击节点展开时就能创建编辑框在节点收缩时就能删除编辑框了,这里的ReFreshEdit()函数非常有用,在这里我使用的是先将这些编辑框删除,然后重现创建的方法,浮云,一切皆是浮云。这个函数同时也起到一个功能就是对于需要滚动条的树控件框中,可以在节点达到边界时继续可以创建编辑框,采用的方法是先将节点文本后添加空格以扩大树控件的右边界,然后在缩小,将我们的编辑框成功显示在节点的后面,在我们使用处理下面事件的时候要经常用到,

 

(1)点击控件的左右滚动条和上下滚动条时

 

afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

都要在消息函数中执行一次ReFreshEdit()函数来及时更新我们编辑框的位置;

(2)在使用鼠标滚轴滚动来调整滚动条时:

afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);

这里同样要调用ReFreshEdit()函数来更新编辑框的位置;

如同1》一样我们在使用编辑框编辑完成后有一个回车提交的动作,我们同样要对我们的编辑框采用同样的消息响应,方法同1.

 

这里我们有个聚焦的动作,当我们在编辑编辑框时我们的焦点在编辑框上,我们键盘回车时我们要将焦点移到我们当前编辑框对应的节点上去,这样才比较合理!

4:最后我们需要将其他事件对应到刷新的操作上来,例如我们有事需手动展开某个节点,键盘调整某个节点,这些都需要我们及时的调用我们的ReFreshEdit()来及时更新节点位置:

5:最后我们可以使用一个清除所有编辑框的函数来清除树控件的所有边界框,以达到我们重新创建树的目的

 

当然本例使用的是第三层节点的创建编辑框的方法,对于多层的可以进行类似的操作

 

 

浮云,一切皆是浮云,我还很菜,以上仅供参考....