当标准的CTreeCtrl不能符合我们的使用要求时,通常会对它进行重载,下面列出若干个技巧。
1,使用Vista的风格
#pragma comment(lib,"UxTheme.lib")
::SetWindowTheme(m_hWnd,L"Explorer", NULL);
2,改变checkbox的图标
新建一个CImageList之后,将自己需要的图标添加进去,然后设置一下
this->SetImageList(&m_iStateIconList,TVSIL_STATE);
前提是,CTreeCtrl的属性中有TVS_CHECKBOXES
3,区分checkbox图标点击和文字被点击的方法
UINT nState; UINT uFlags = 0; HTREEITEM selectItem = HitTest(point, &uFlags); if(selectItem == NULL) { return; } if(!(uFlags & TVHT_ONITEMSTATEICON)) { //item clicked //you want do } else { //nState: 0->No ChenckBox // 1->No Select State // 2->Some Select // 3->All Select nState = GetItemState(selectItem,TVIS_STATEIMAGEMASK) >>12; nState=(nState==3)?1:3; }
注意,如果处理中发生了展开或者收缩的情况的话,hittest有错的时候。
4,更改树显示的背景以及文字颜色
void CTreeCtrlEx::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTVCUSTOMDRAW pNMCD = reinterpret_cast
5,遍历修改checkbox的状态
重载SetItemState函数之后,调用下面2个遍历函数。
BOOL CTreeCtrlEx::SetItemState(HTREEITEM hItem, UINT nState,UINT nStateMask, BOOL bSearch) { BOOL bReturn=CTreeCtrl::SetItemState( hItem, nState, nStateMask ); UINT iState = nState >> 12; if(iState!=0) { if(bSearch) TravelChild(hItem, iState); TravelSiblingAndParent(hItem,iState); } return bReturn; } void CTreeCtrlEx::TravelSiblingAndParent(HTREEITEM hItem, int nState) { HTREEITEM hNextSiblingItem,hPrevSiblingItem,hParentItem; //Find parent node if not exists return; hParentItem=GetParentItem(hItem); if(hParentItem!=NULL) { int nState1=nState; //Find The Node State after Currently node hNextSiblingItem=GetNextSiblingItem(hItem); while(hNextSiblingItem!=NULL) { nState1 = GetItemState( hNextSiblingItem, TVIS_STATEIMAGEMASK ) >> 12; if(nState1!=nState && nState1!=0) break; else hNextSiblingItem=GetNextSiblingItem(hNextSiblingItem); } if(nState1==nState) { //Find The Node State before Currently node hPrevSiblingItem=GetPrevSiblingItem(hItem); while(hPrevSiblingItem!=NULL) { nState1 = GetItemState(hPrevSiblingItem,TVIS_STATEIMAGEMASK)>> 12; if(nState1!=nState && nState1!=0) break; else hPrevSiblingItem=GetPrevSiblingItem(hPrevSiblingItem); } } if(nState1==nState || nState1==0) { nState1 = GetItemState( hParentItem, TVIS_STATEIMAGEMASK ) >> 12; if(nState1!=0) { CTreeCtrl::SetItemState( hParentItem,INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK ); } TravelSiblingAndParent(hParentItem,nState); } else { //third state hParentItem=GetParentItem(hItem); while(hParentItem!=NULL) { nState1 = GetItemState( hParentItem, TVIS_STATEIMAGEMASK ) >> 12; if(nState1!=0) { CTreeCtrl::SetItemState( hParentItem, INDEXTOSTATEIMAGEMASK(2), TVIS_STATEIMAGEMASK ); } hParentItem=GetParentItem(hParentItem); } } } } void CTreeCtrlEx::TravelChild(HTREEITEM hItem, int nState) { HTREEITEM hChildItem,hBrotherItem; hChildItem=GetChildItem(hItem); if(hChildItem!=NULL) { CTreeCtrl::SetItemState(hChildItem,INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK ); TravelChild(hChildItem, nState); hBrotherItem=GetNextSiblingItem(hChildItem); while (hBrotherItem) { int nState1 = GetItemState( hBrotherItem, TVIS_STATEIMAGEMASK ) >> 12; if(nState1!=0) { CTreeCtrl::SetItemState( hBrotherItem, INDEXTOSTATEIMAGEMASK(nState),TVIS_STATEIMAGEMASK ); } TravelChild(hBrotherItem, nState); hBrotherItem=GetNextSiblingItem(hBrotherItem); } } }