原文地址:CTreeCtrl消息处理作者:蓝猫之家
1. 定义变量 CTreeCtrl m_T;
2. 显示样式
3. 消息事件
(1)鼠标点击当前ITEM的CHECKBOX:引发NM_CLICK事件并传递TVHT_ONITEMSTATEICON。
(2)鼠标点击当前ITEM的TEXT:引发NM_CLICK事件。
(3)鼠标点击新ITEM的CHECKBOX:引发TVN_SELCHANGED事件、NM_CLICK事件并传递TVHT_ONITEMSTATEICON。
(4)鼠标点击新ITEM的TEXT:引发NM_CLICK事件、TVN_SELCHANGED事件。
4. 消息事件总结
点击ITEM会引发NM_CLICK事件。若点击CHECKBOX则传递TVHT_ONITEMSTATEICON。
因此可不处理TVN_SELCHANGED事件而只处理NM_CLICK事件。
5. 消息处理注意事项
(1)点击CHECKBOX后会自动更新CheckBox的状态,因此在处理代码中不需要使用SetCheck函数设置状态,而GetCheck函数返回也是其原始状态。
(2)点击新CHECKBOX后不会自动将对应的ITEM设置为选择状态,需要使用SelectItem函数进行设置。
6. 使用方法
(1)若传递TVHT_ONITEMSTATEICON
获取选择ITEM的状态并取反
若有子项则所有子项设置为一致
若没有子项则
若当前状态为TRUE则设置父项为TRUE;否则遍历所有兄弟项,若全为FALSE则设置父项为FALSE。
若选择了新ITEM则设置新ITEM为选择项
(2)若未传递TVHT_ONITEMSTATEICON
设置更新ITEM状态,获取选择ITEM的状态
若有子项则所有子项设置为一致
若没有子项则
若当前状态为TRUE则设置父项为TRUE;否则遍历所有兄弟项,若全为FALSE则设置父项为FALSE。
7. 响应NM_CLICK事件的函数代码
void myDialog::OnClickT(NMHDR* pNMHDR,LRESULT* pResult)
{
//添加代码
//获取鼠标位置
CPoint cP;
UINT uF=0;
GetCursorPos(&cP);
m_T.ScreenToClient(&cP);
//获取位置对应的ITEM
HTREEITEM hItem=m_T.HitTest(cP,&uF);
//获取当前选择项ITEM
HTREEITEM hItemSel=m_T.GetSelectItem();
//若鼠标在ITEM外则退出
if(TVHT_NOWHERE & uF)
return;
//处理:传递TVHT_ONITEMSTATEICON
if(TVHT_ONITEMSTATEICON & uF)
{
BOOL bChk=!m_T.GetCheck(hItem);
//父项处理
if(m_T.ItemHasChildren(hItem))
{
HTREEITEM hChildItem=m_T.GetChildItem(hItem);
while(hChildItem!=NULL)
{
m_T.SetCheck(hChildItem,bChk);
hChildItem=m_T.GetNextItem(hChildItem,TVGN_NEXT);
}
}
//兄弟项处理
BOOL bFalse;
bFalse=0;
if(!m_T.ItemHasChildren(hItem))
{
HTREEITEM hParentItem=m_T.GetParentItem(hItem);
if(bChk)
m_T.SetCheck(hParentItem,bChk);
if(!bChk)
{
HTREEITEM hChildItem=m_T.GetChildItem(hItem);
while(hChildItem!=NULL & bFalse==0)
{
if(hChildItem!=hItem)
bFalse=m_T.GetCheck(hChildItem);
hChildItem=m_T.GetNextItem(hChildItem,TVGN_NEXT);
}
if(bFalse==0)
m_T.SetCheck(hParentItem,bChk);
}
}
}
//处理:不传递TVHT_ONITEMSTATEICON
else
{
m_T.SetCheck(hItem,!m_T.GetCheck(hItem));
BOOL bChk=m_T.GetCheck(hItem);
//父项处理
if(m_T.ItemHasChildren(hItem))
{
HTREEITEM hChildItem=m_T.GetChildItem(hItem);
while(hChildItem!=NULL)
{
m_T.SetCheck(hChildItem,bChk);
hChildItem=m_T.GetNextItem(hChildItem,TVGN_NEXT);
}
}
//兄弟项处理
BOOL bFalse;
bFalse=0;
if(!m_T.ItemHasChildren(hItem))
{
HTREEITEM hParentItem=m_T.GetParentItem(hItem);
if(bChk)
m_T.SetCheck(hParentItem,bChk);
if(!bChk)
{
HTREEITEM hChildItem=m_T.GetChildItem(hItem);
while(hChildItem!=NULL & bFalse==0)
{
if(hChildItem!=hItem)
bFalse=m_T.GetCheck(hChildItem);
hChildItem=m_T.GetNextItem(hChildItem,TVGN_NEXT);
}
if(bFalse==0)
m_T.SetCheck(hParentItem,bChk);
}
}
}
//添加代码结束
*pResult=0;
}