C++ CTreeview的checkbox使用方法
1.消息事件
(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事件。
2.消息事件总结
点击ITEM会引发NM_CLICK事件。若点击CHECKBOX则传递TVHT_ONITEMSTATEICON。
因此可不处理TVN_SELCHANGED事件而只处理NM_CLICK事件。
3.消息处理注意事项
(1)点击CHECKBOX后会自动更新CheckBox的状态,因此在处理代码中不需要使用SetCheck函数设置状态,而GetCheck函数返回也是其原始状态。
(2)点击新CHECKBOX后不会自动将对应的ITEM设置为选择状态,需要使用SelectItem函数进行设置。
4.使用方法
(1)若传递TVHT_ONITEMSTATEICON
获取选择ITEM的状态并取反
若有子项则所有子项设置为一致
若没有子项则
若当前状态为TRUE则设置父项为TRUE;否则遍历所有兄弟项,若全为FALSE则设置父项为FALSE。
若选择了新ITEM则设置新ITEM为选择项
(2)若未传递TVHT_ONITEMSTATEICON
设置更新ITEM状态,获取选择ITEM的状态
若有子项则所有子项设置为一致
若没有子项则
若当前状态为TRUE则设置父项为TRUE;否则遍历所有兄弟项,若全为FALSE则设置父项为FALSE。
5.响应NM_CLICK事件的函数代码
voidCTestTimerDlg::OnClickTree(NMHDR*pNMHDR,LRESULT*pResult) { //TODO:Addyourcontrolnotificationhandlercodehere CPointpoint; UINTuFlag;//接收有关点击测试的信息的整数 HTREEITEMhTree; BOOLbCheck; GetCursorPos(&point);//获取屏幕鼠标坐标 m_TreeCtrl.ScreenToClient(&point);//转化成客户坐标 hTree=m_TreeCtrl.HitTest(point,&uFlag);//返回与CtreeTtrl关联的光标的当前位置和句柄 if((TVHT_NOWHERE&uFlag)) { return; } if(hTree&&(TVHT_ONITEMSTATEICON&uFlag))//点中复选框 { m_TreeCtrl.SelectItem(hTree); CStringtemp=m_TreeCtrl.GetItemText(hTree)+"\r\n"; TRACE(temp); bCheck=m_TreeCtrl.GetCheck(hTree);//获取当前复选状态 SetChildCheck(hTree,!bCheck);//设置子项复选状态 SetParentCheck(hTree,bCheck);//设置父项复选状态 } *pResult=0; }
voidCTestTimerDlg::SetChildCheck(HTREEITEMhTree,BOOLbCheck) { m_TreeCtrl.Expand(hTree,TVE_EXPAND); hTree=m_TreeCtrl.GetChildItem(hTree);//获取子项句柄 while(hTree) { m_TreeCtrl.SetCheck(hTree,bCheck); SetChildCheck(hTree,bCheck);//递归调用 hTree=m_TreeCtrl.GetNextSiblingItem(hTree);//获取兄弟的句柄 } }
voidCTestTimerDlg::SetParentCheck(HTREEITEMhTree,BOOLbCheck) { HTREEITEMhParent=m_TreeCtrl.GetParentItem(hTree); if(hParent) { HTREEITEMhChild=m_TreeCtrl.GetChildItem(hParent); while(hChild) { if(hChild==hTree) { hChild=m_TreeCtrl.GetNextSiblingItem(hChild); continue; } BOOLbflag=m_TreeCtrl.GetCheck(hChild); if(bCheck==bflag)//判断是否还有兄弟项被选择 { return; } hChild=m_TreeCtrl.GetNextSiblingItem(hChild); } m_TreeCtrl.SetCheck(hParent,!bCheck); SetParentCheck(hParent,bCheck);//设置父项的状态 }