84上位机VC MFC树视图三种节点状态效果
84上位机VC MFC树视图三种节点状态效果
功能展示
树视图节点有不同状态的复选框效果,可以让用户更多清楚的了解自己当前的操作情况,我们当前这例程就来实现三种不同状态的节点功能,效果如图; 要点提示 树状视图的复选框是通过图像状态索引绘制,我们先设计一个位图,包含视图项的各个状态,再将位图添加械CImageList中,然后调用CTreeCtrl的SetImageList()就可以设置位图状态索引; 实现功能 1.新建基于对话框的应用程序 2.派生一个自己的类class CStateTreeCtrl : publicCTreeCtrl;给类添加三个函数 voidRansackParentAndChild(HTREEITEM hItem,UINT State); void RansackChild(HTREEITEM hItem,UINT State); BOOL SetItemState(HTREEITEM hItem, UINT State, UINTStateMask, BOOL IsSearch=TRUE);
再添加nLButtonDown(UINTnFlags, CPoint point) 和voidCStateTreeCtrl:reSubclassWindow() 函数,下面是这五个函数的函数体 - void CStateTreeCtrl::PreSubclassWindow()
- {
- ModifyStyle(0,TVS_CHECKBOXES|TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT|TVS_FULLROWSELECT,0);
- CTreeCtrl::PreSubclassWindow();
- }
- void CStateTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- HTREEITEM hItemInfo =HitTest(point, &nFlags);
- //TVHT_ONITEMSTATEICON表示用户定义的视图项的图标状态
- if ( nFlags &TVHT_ONITEMSTATEICON )
- {
- //State: 0无状态 1没有选择 2部分选择 3全部选择
- //12到15位表示视图项的图像状态索引
- UINT State = GetItemState( hItemInfo, TVIS_STATEIMAGEMASK ) >> 12;
- State=(State==3)?1:3;
- SetItemState( hItemInfo, INDEXTOSTATEIMAGEMASK(State), TVIS_STATEIMAGEMASK );
- }
- else
- CTreeCtrl::OnLButtonDown(nFlags, point);
- }
复制代码- //遍历子节点
- void CStateTreeCtrl::RansackChild(HTREEITEM hItem, UINT State)
- {
- HTREEITEM hChildItem,hBrotherItem;
- //查找子节点
- hChildItem=GetChildItem(hItem);
- if(hChildItem!=NULL)
- {
- //将所有子节点的状态设置与父节点相同
- CTreeCtrl::SetItemState( hChildItem, INDEXTOSTATEIMAGEMASK(State), TVIS_STATEIMAGEMASK );
- //再递归处理子节点的子节点
- RansackChild(hChildItem, State);
-
- //搜索子节点的兄弟节点
- hBrotherItem=GetNextSiblingItem(hChildItem);
- while (hBrotherItem)
- {
- //设置子节点的兄弟节点状态与当前节点的状态一致
- int nState = GetItemState( hBrotherItem, TVIS_STATEIMAGEMASK ) >> 12;
- if(nState!=0)
- {
- CTreeCtrl::SetItemState( hBrotherItem, INDEXTOSTATEIMAGEMASK(State), TVIS_STATEIMAGEMASK );
- }
- //再递归处理兄弟节点
- RansackChild(hBrotherItem, State);
- hBrotherItem=GetNextSiblingItem(hBrotherItem);
- }
- }
- }
- void CStateTreeCtrl::RansackParentAndChild(HTREEITEM hItem, UINT State)
- {
- HTREEITEM hNextItem,hPrevItem,hParentItem;
-
- //查找父节点,没有就结束
- hParentItem=GetParentItem(hItem);
- if(hParentItem!=NULL)
- {
- UINT nState1=State;//设初始值,防止没有兄弟节点时出错
-
- //查找当前节点的所有兄弟节点,如果所有兄弟节点状态都相同,
- //设置父节点的状态
-
复制代码- //查找当前节点下面的兄弟节点的状态
- hNextItem=GetNextSiblingItem(hItem);
- while(hNextItem!=NULL)
- {
- nState1 = GetItemState( hNextItem, TVIS_STATEIMAGEMASK ) >> 12;
- if(nState1!=State && nState1!=0) break;
- else hNextItem=GetNextSiblingItem(hNextItem);
- }
-
- if(nState1==State)
- {
- //查找当前节点上面的兄弟节点的状态
- hPrevItem=GetPrevSiblingItem(hItem);
- while(hPrevItem!=NULL)
- {
- nState1 = GetItemState( hPrevItem, TVIS_STATEIMAGEMASK ) >> 12;
- if(nState1!=State && nState1!=0) break;
- else hPrevItem=GetPrevSiblingItem
- (hPrevItem);
- }
- }
- if(nState1==State || nState1==0)
- {
- nState1 = GetItemState( hParentItem, TVIS_STATEIMAGEMASK ) >> 12;
- if(nState1!=0)
- {
- //如果状态一致,则父节点的状态与当前节点的状态一致
- CTreeCtrl::SetItemState( hParentItem, INDEXTOSTATEIMAGEMASK(State), TVIS_STATEIMAGEMASK );
- }
- //再递归处理父节点的兄弟节点和其父节点
- RansackParentAndChild(hParentItem,State);
- }
- else
- {
- //状态不一致,则当前节点的父节点、父节点的父节点……状态均为第三态
- 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);
- }
- }
- }
- }
复制代码- while(hParentItem!=NULL)
- {
- nState1 = GetItemState( hParentItem, TVIS_STATEIMAGEMASK ) >> 12;
- if(nState1!=0)
- {
- CTreeCtrl::SetItemState( hParentItem, INDEXTOSTATEIMAGEMASK(2), TVIS_STATEIMAGEMASK );
- }
- hParentItem=GetParentItem(hParentItem);
- }
- }
- }
- }
- //设置节点状态
- BOOL CStateTreeCtrl::SetItemState(HTREEITEM hItem, UINT State, UINT StateMask, BOOL IsSearch)
- {
- BOOL ret=CTreeCtrl::SetItemState( hItem, State, StateMask );
- UINT nState =State >> 12;
- if(nState!=0)
- {
- if(IsSearch)
- RansackChild(hItem, nState);
- RansackParentAndChild(hItem,nState);
- }
- return ret;
- }
复制代码4.最后是这个自定义类的使用;主对话框中添加数着视图关联变量 CStateTreeCtrl m_Tree;添加两变量 CImageList m_ImageList; CImageList m_StateList;
5.初始化给树状视图添加数据 - m_ImageList.Create(IDB_BITMAP1,16,1,RGB(255,255,255));
- m_StateList.Create(IDB_BITMAP2,12,1,RGB(255,255,255));
- m_Tree.SetImageList(&m_ImageList,TVSIL_NORMAL);
- m_Tree.SetImageList(&m_StateList,TVSIL_STATE);
- TV_INSERTSTRUCT hInsert;
- hInsert.hParent=NULL;
- hInsert.hInsertAfter=TVI_LAST;
- hInsert.item.mask=TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_STATE;
- hInsert.item.hItem=NULL;
- hInsert.item.state=INDEXTOSTATEIMAGEMASK( 1 );
复制代码- hInsert.item.stateMask=TVIS_STATEIMAGEMASK;
- hInsert.item.cchTextMax=6;
- hInsert.item.iSelectedImage=1;
- hInsert.item.cChildren=0;
- hInsert.item.lParam=0;
- hInsert.item.pszText="工控编程";
- hInsert.item.iImage=0;
- HTREEITEM hRoot=m_Tree.InsertItem(&hInsert);
- m_Tree.SetItemState( hRoot, INDEXTOSTATEIMAGEMASK(0), TVIS_STATEIMAGEMASK );
- hInsert.hParent=hRoot;
- hInsert.item.iImage=0;
- hInsert.item.pszText="欧姆龙PLC编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=hRoot;
- hInsert.item.pszText="三菱PLC编程";
- HTREEITEM h1=m_Tree.InsertItem(&hInsert);
- hInsert.hParent=hRoot;
- hInsert.item.pszText="西门子PLC编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=hRoot;
- hInsert.item.pszText="松下PLC编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=hRoot;
- hInsert.item.pszText="罗克韦尔PLC编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=hRoot;
- hInsert.item.pszText="其他编程";
- HTREEITEM h2=m_Tree.InsertItem(&hInsert);
- hInsert.hParent=h2;
- hInsert.item.pszText="上位机VC编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=h2;
- hInsert.item.pszText="触摸屏编程";
- m_Tree.InsertItem(&hInsert);
- hInsert.hParent=h2;
- hInsert.item.pszText="贝加莱PLC编程";
- m_Tree.InsertItem(&hInsert);
-
- hInsert.hParent=h2;
- hInsert.item.pszText="组态编程";
- m_Tree.InsertItem(&hInsert);
- <div style="text-align: center;"><span style="line-height: 1.5;"><b><font size="4">我们来演示下实现过程</font></b></span></div>
复制代码
|