www.gusucode.com > VC++三态树多个注册表子键的浏览及选择-源码程序 > VC++三态树多个注册表子键的浏览及选择-源码程序\code\RegisterTreeCtrl.cpp
// RegisterTreeCtrl.cpp : implementation file // Download by http://www.NewXing.com #include "stdafx.h" #include "RegisterTreeCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CRegisterTreeCtrl CRegisterTreeCtrl::CRegisterTreeCtrl() { m_uFlags = 0; } CRegisterTreeCtrl::~CRegisterTreeCtrl() { } BEGIN_MESSAGE_MAP(CRegisterTreeCtrl, CTreeCtrl) //{{AFX_MSG_MAP(CRegisterTreeCtrl) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded) ON_NOTIFY_REFLECT(NM_CLICK, OnClick) ON_WM_LBUTTONDOWN() ON_WM_KEYDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRegisterTreeCtrl message handlers const HKEY hRoot[] = {HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA }; const char* strRoot[] = {"HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CURRENT_CONFIG", "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA" }; BOOL CRegisterTreeCtrl::DisplayTree(BOOL bWinNT) { DeleteAllItems(); DisplayDrives(bWinNT); return TRUE; } BOOL CRegisterTreeCtrl::DisplayDrives(BOOL bWinNT) { UINT nSize = sizeof(hRoot)/sizeof(hRoot[0]); UINT nCycle = 0; while( nCycle < nSize ) { if(IsExist(hRoot[nCycle],NULL)) { HTREEITEM hParent = AddItem( TVI_ROOT, strRoot[nCycle] ,hRoot[nCycle]); if ( FindSubDir( hRoot[nCycle],NULL ) ) InsertItem( "", 0, 0, hParent ); } nCycle++; } return TRUE; } BOOL CRegisterTreeCtrl::IsExist(HKEY hKey,LPCTSTR lpSubKey) { HKEY phkResult; if( ERROR_SUCCESS == RegOpenKeyEx(hKey,lpSubKey,0, KEY_EXECUTE,&phkResult)) { RegCloseKey(phkResult); return TRUE; } return FALSE; } HTREEITEM CRegisterTreeCtrl::AddItem(HTREEITEM hParent, LPCTSTR strPath, HKEY hKey) { CString strTemp = strPath; HTREEITEM hReturn; if ( hParent == TVI_ROOT ) { hReturn = InsertItem(TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_STATE, (LPCTSTR)strTemp,0,1,INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK,0,hParent,TVI_LAST); SetItemData(hReturn,(DWORD)hKey); return hReturn; } hReturn = InsertItem(TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_STATE, (LPCTSTR)strTemp,0,1,INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK,0,hParent,TVI_LAST); SetItemData(hReturn,(DWORD)hKey); return hReturn; } BOOL CRegisterTreeCtrl::FindSubDir(HKEY hKey,LPCTSTR lpSubKey) { if(IsExist(hKey,lpSubKey)) { HKEY phkResult; if( ERROR_SUCCESS == RegOpenKeyEx(hKey,lpSubKey,0, KEY_READ,&phkResult)) { char sz[MAX_PATH]; if( ERROR_SUCCESS == RegEnumKey(phkResult,0,sz,MAX_PATH)) { RegCloseKey(phkResult); return TRUE; } RegCloseKey(phkResult); } } return FALSE; } void CRegisterTreeCtrl::ExpandItem(HTREEITEM hItem, UINT nCode) { CString strSubKey; if ( nCode == TVE_EXPAND ) { HTREEITEM hChild = GetChildItem( hItem ); while ( hChild ) { DeleteItem( hChild ); hChild = GetChildItem( hItem ); } HKEY hKey = (HKEY)GetItemData(hItem); strSubKey = GetSubKey(hItem); if(strSubKey.IsEmpty()) DisplayPath( hItem, NULL ,hKey ); else DisplayPath( hItem, strSubKey ,hKey ); } } void CRegisterTreeCtrl::DisplayPath(HTREEITEM hParent, LPCTSTR lpSubKey , HKEY hKey) { HKEY phkResult; char sz[MAX_PATH]; DWORD nReturn; CString strSubKey = lpSubKey; CString strName; if( ERROR_SUCCESS != RegOpenKeyEx(hKey,lpSubKey,0, KEY_READ,&phkResult)) { return; } CWaitCursor wc; SetRedraw( FALSE ); for(int i=0 ; ; i++) { nReturn = RegEnumKey(phkResult,i,sz,MAX_PATH); if( nReturn != ERROR_SUCCESS ) break; HTREEITEM hItem = AddItem( hParent , sz , hKey); strName.Format("%s",sz); if(lpSubKey == NULL) { strSubKey = strName; } else { strSubKey.Format("%s",lpSubKey); strSubKey += "\\" + strName; } if (FindSubDir(hKey , strSubKey)) InsertItem( "", 0, 0, hItem ); } RegCloseKey(phkResult); //nState: 0->无选择钮 1->没有选择 2->部分选择 3->全部选择 UINT nState = GetItemState( hParent, TVIS_STATEIMAGEMASK ) >> 12; if(nState == 3) SetItemState( hParent, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK ); SetRedraw( TRUE ); } void CRegisterTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; CString strPath; if ( pNMTreeView->itemNew.state & TVIS_EXPANDED ) { ExpandItem( pNMTreeView->itemNew.hItem, TVE_EXPAND ); } else { HTREEITEM hChild = GetChildItem( pNMTreeView->itemNew.hItem ); while ( hChild ) { DeleteItem( hChild ); hChild = GetChildItem( pNMTreeView->itemNew.hItem ); } InsertItem( "", pNMTreeView->itemNew.hItem ); } *pResult = 0; } CString CRegisterTreeCtrl::GetSubKey(HTREEITEM hItem) { CString strReturn; CString strTemp; int nIndex = 0; HTREEITEM hParent = hItem; strReturn = ""; while ( hParent ) { strTemp = GetItemText( hParent ); strTemp += "\\"; strReturn = strTemp + strReturn; hParent = GetParentItem( hParent ); } strReturn.TrimRight( '\\' ); nIndex = strReturn.Find("\\"); if(nIndex == -1) strReturn = ""; else strReturn = strReturn.Right(strReturn.GetLength()-nIndex-1); return strReturn; } BOOL CRegisterTreeCtrl::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 CRegisterTreeCtrl::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 CRegisterTreeCtrl::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); } } } } void CRegisterTreeCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) { if(m_uFlags & TVHT_ONITEMSTATEICON) *pResult=1; else *pResult = 0; } void CRegisterTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) { HTREEITEM hItem = HitTest(point, &m_uFlags); 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 CRegisterTreeCtrl::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); } void CRegisterTreeCtrl::CalcuSelectPath() { UINT nState; HTREEITEM hParent; CString strPath; m_strlist.RemoveAll(); hParent = GetRootItem(); while( hParent != NULL ) { nState = GetItemState( hParent, TVIS_STATEIMAGEMASK ) >> 12; switch(nState) { case 2: strPath = GetItemText(hParent); CalcuSelectSubPath(hParent,strPath); break; case 3: strPath = GetItemText(hParent); //strPath += "\\"; m_strlist.AddTail(strPath); break; } hParent = GetNextSiblingItem(hParent); }; } void CRegisterTreeCtrl::CalcuSelectSubPath(HTREEITEM hParent,CString strPath) { UINT nState; HTREEITEM hItem = GetChildItem(hParent); CString strPathName; CString strDirectory(strPath); CString strTemp; while( hItem != NULL ) { nState = GetItemState( hItem, TVIS_STATEIMAGEMASK ) >> 12; switch(nState) { case 2: strPathName = GetItemText(hItem); strTemp = strDirectory; strTemp += "\\" + strPathName; CalcuSelectSubPath(hItem,strTemp); break; case 3: strPathName = GetItemText(hItem); strTemp = strDirectory; strTemp += "\\" + strPathName; m_strlist.AddTail(strTemp); break; } hItem = GetNextSiblingItem(hItem); }; } CStringList* CRegisterTreeCtrl::GetSelectKey() { CalcuSelectPath(); if(m_strlist.IsEmpty()) return NULL; return &m_strlist; }