MFC,实现三态树形控件以及父子节点联动

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MFC,实现三态树形控件以及父子节点联动
首先创建CXPTreeCtrl继承与CTreeCtrl,下面是头文件
class CXPTreeCtrl : public CTreeCtrl
{
// Construction
public:
CXPTreeCtrl();
// Attributes
public:
HBITMAP m_hBmpScrollBar ;
// Operations
public:
void SetCheckBoxBitMap(UINT ID)//在主对话框中使用,用于加载checkbox位图
{
m_imgState.Create(ID,13, 1, RGB(255,255,255));
SetImageList(&m_imgState,TVSIL_STATE);
}
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CXPTreeCtrl)
//}}AFX_VIRTUAL
// Implementation
public:
BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask, BOOL bSearch=TRUE);
virtual ~CXPTreeCtrl();
// Generated message map functions
protected:
//{{AFX_MSG(CXPTreeCtrl)
afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
UINT m_uFlags;
void TravelSiblingAndParent(HTREEITEM hItem, int nState);
void TravelChild(HTREEITEM hItem, int nState);
CImageList m_imgState;
};

然后是实现文件
// XPTreeCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "XPTreeCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////// //////////
// CXPTreeCtrl
CXPTreeCtrl::CXPTreeCtrl()
{
m_uFlags=0;
}
CXPTreeCtrl::~CXPTreeCtrl()
{
}
BEGIN_MESSAGE_MAP(CXPTreeCtrl, CTreeCtrl)
//{{AFX_MSG_MAP(CXPTreeCtrl)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
ON_WM_LBUTTONDOWN()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////// //////////
// CXPTreeCtrl message handlers
void CXPTreeCtrl::OnClick(NMHDR* pNMHDR, LRESULT*
pResult)
{
if(m_uFlags&TVHT_ONITEMSTATEICON) *pResult=1;
else *pResult = 0;
}
void CXPTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) {
HTREEITEM hItem =HitTest(point, &m_uFlags);
if (hItem != NULL)
{
SetFocus();
SelectItem(hItem);
}
if ( (m_uFlags&TVHT_ONITEMSTATEICON ))
{
//nState: 0->无选择钮 1->没有选择 2->部分选择 3->全部选择
UINT nState = GetItemState( hItem, TVIS_STATEIMAGEMASK ) >> 12;
nState=(nState==3)?1:3;
SetItemState( hItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK );
}
CTreeCtrl::OnLButtonDown(nFlags, point);
}
void CXPTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
//处理空格键
if(nChar==0x20)
{
HTREEITEM hItem =GetSelectedItem();
UINT nState = GetItemState( hItem, TVIS_STATEIMAGEMASK ) >> 12;
if(nState!=0)
{
nState=(nState==3)?1:3;
SetItemState( hItem, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK );
}
}
else CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CXPTreeCtrl::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 CXPTreeCtrl::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);
}
}
void CXPTreeCtrl::TravelSiblingAndParent(HTREEITEM hItem, int nState)
{
HTREEITEM hNextSiblingItem,hPrevSiblingItem,hParentItem;
//查找父节点,没有就结束
hParentItem=GetParentItem(hItem);
if(hParentItem!=NULL)
{
int nState1=nState;//设初始值,防止没有兄弟节点时出错
//查找当前节点下面的兄弟节点的状态
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)
{
//查找当前节点上面的兄弟节点的状态
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
{
//状态不一致,则当前节点的父节点、父节点的父节点……状态均为第三态
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);
}
}
}
}



以上就实现了三态树的所有功能,接下来是使用方法
假设主对话框是CMyDlg,此时已经通过DDX添加了树形控件CTreeCtrl m_treeCtrl
把CTreeCtrl m_treeCtrl 改为 CXPTreeCtrl m_treeCtrl
重载BOOL OnInitDialog();
在其中添加以下代码,主要是加载checkbox的位图
//加载树形控件的资源,假设加载的位图ID是IDB_MultiTreeCheckBox
m_treeCtrl.SetCheckBoxBitMap(IDB_MultiTreeCheckBox);

如果要获取当前checkbox的状态
//其中 nState: 0->无选择钮 1->没有选择 2->部分选择 3->全部选择
UINT nState = m_treeCtrl.GetItemState( cItem, TVIS_STATEIMAGEMASK ) >> 12;

设置当前checkbox的状态
//SetItemState()是被重载过的函数,因此这样设置后,父子节点会保持一致
//同样0->无选择钮1->没有选择2->部分选择3->全部选择,数字填在INDEXTOSTATEIMAGEMASK()中
m_treeCtrl.SetItemState(item, INDEXTOSTATEIMAGEMASK(3), TVIS_STATEIMAGEMASK );

整体的三态树形控件就是这样创建和使用的。

相关文档
最新文档