2326 lines
66 KiB
C++
2326 lines
66 KiB
C++
|
/*******************************************************************************
|
||
|
*
|
||
|
* treeview.cpp
|
||
|
*
|
||
|
* implementation of the CAdminTreeView class
|
||
|
*
|
||
|
* copyright notice: Copyright 1997, Citrix Systems Inc.
|
||
|
* Copyright (c) 1998 - 1999 Microsoft Corporation
|
||
|
* $Author: donm $ Don Messerli
|
||
|
*
|
||
|
* $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\treeview.cpp $
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "winadmin.h"
|
||
|
#include "admindoc.h"
|
||
|
#include "treeview.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
extern DWORD g_dwTreeViewExpandedStates;
|
||
|
/////////////////////////////
|
||
|
// MESSAGE MAP: CAdminTreeView
|
||
|
//
|
||
|
IMPLEMENT_DYNCREATE(CAdminTreeView, CBaseTreeView)
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(CAdminTreeView, CBaseTreeView)
|
||
|
//{{AFX_MSG_MAP(CAdminTreeView)
|
||
|
ON_MESSAGE(WM_ADMIN_ADD_SERVER, OnAdminAddServer)
|
||
|
ON_MESSAGE(WM_ADMIN_REMOVE_SERVER, OnAdminRemoveServer)
|
||
|
ON_MESSAGE(WM_ADMIN_UPDATE_SERVER, OnAdminUpdateServer)
|
||
|
ON_MESSAGE(WM_ADMIN_ADD_WINSTATION, OnAdminAddWinStation)
|
||
|
ON_MESSAGE(WM_ADMIN_UPDATE_WINSTATION, OnAdminUpdateWinStation)
|
||
|
ON_MESSAGE(WM_ADMIN_REMOVE_WINSTATION, OnAdminRemoveWinStation)
|
||
|
ON_MESSAGE(WM_ADMIN_UPDATE_DOMAIN, OnAdminUpdateDomain)
|
||
|
ON_MESSAGE(WM_ADMIN_ADD_DOMAIN, OnAdminAddDomain)
|
||
|
ON_MESSAGE(WM_ADMIN_VIEWS_READY, OnAdminViewsReady)
|
||
|
ON_MESSAGE( WM_ADMIN_ADDSERVERTOFAV , OnAdminAddServerToFavs )
|
||
|
ON_MESSAGE( WM_ADMIN_REMOVESERVERFROMFAV , OnAdminRemoveServerFromFavs )
|
||
|
ON_MESSAGE( WM_ADMIN_GOTO_SERVER , OnAdminGotoServer )
|
||
|
ON_MESSAGE( WM_ADMIN_DELTREE_NODE , OnAdminDelFavServer )
|
||
|
ON_MESSAGE( WM_ADMIN_GET_TV_STATES , OnGetTVStates )
|
||
|
ON_MESSAGE( WM_ADMIN_UPDATE_TVSTATE , OnUpdateTVState )
|
||
|
ON_MESSAGE( IDM_ALLSERVERS_EMPTYFAVORITES , OnEmptyFavorites )
|
||
|
ON_MESSAGE( WM_ISFAVLISTEMPTY , OnIsFavListEmpty )
|
||
|
ON_MESSAGE( WM_ADMIN_CONNECT_TO_SERVER, OnAdminConnectToServer )
|
||
|
ON_WM_CONTEXTMENU()
|
||
|
|
||
|
/*
|
||
|
ON_WM_LBUTTONUP( )
|
||
|
ON_WM_MOUSEMOVE( )
|
||
|
ON_WM_TIMER( )
|
||
|
ON_NOTIFY( TVN_BEGINDRAG , AFX_IDW_PANE_FIRST , OnBeginDrag )
|
||
|
*/
|
||
|
|
||
|
|
||
|
ON_NOTIFY( NM_RCLICK , AFX_IDW_PANE_FIRST , OnRClick )
|
||
|
|
||
|
ON_WM_LBUTTONDBLCLK()
|
||
|
ON_COMMAND( ID_ENTER , OnEnterKey )
|
||
|
ON_WM_SETFOCUS( )
|
||
|
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
//////////////////////////
|
||
|
// F'N: CAdminTreeView ctor
|
||
|
//
|
||
|
CAdminTreeView::CAdminTreeView()
|
||
|
{
|
||
|
m_pimgDragList = NULL;
|
||
|
m_hDragItem = NULL;
|
||
|
|
||
|
} // end CAdminTreeView ctor
|
||
|
|
||
|
|
||
|
//////////////////////////
|
||
|
// F'N: CAdminTreeView dtor
|
||
|
//
|
||
|
CAdminTreeView::~CAdminTreeView()
|
||
|
{
|
||
|
|
||
|
} // end CAdminTreeView dtor
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
//////////////////////////////////
|
||
|
// F'N: CAdminTreeView::AssertValid
|
||
|
//
|
||
|
void CAdminTreeView::AssertValid() const
|
||
|
{
|
||
|
CBaseTreeView::AssertValid();
|
||
|
|
||
|
} // end CAdminTreeView::AssertValid
|
||
|
|
||
|
|
||
|
///////////////////////////
|
||
|
// F'N: CAdminTreeView::Dump
|
||
|
//
|
||
|
void CAdminTreeView::Dump(CDumpContext& dc) const
|
||
|
{
|
||
|
CBaseTreeView::Dump(dc);
|
||
|
|
||
|
} // end CAdminTreeView::Dump
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::BuildImageList
|
||
|
//
|
||
|
// - calls m_imageList.Create(..) to create the image list
|
||
|
// - calls AddIconToImageList(..) to add the icons themselves and save
|
||
|
// off their indices
|
||
|
// - attaches the image list to the CTreeCtrl
|
||
|
//
|
||
|
void CAdminTreeView::BuildImageList()
|
||
|
{
|
||
|
m_ImageList.Create(16, 16, TRUE, 19, 0);
|
||
|
|
||
|
m_idxBlank = AddIconToImageList(IDI_BLANK);
|
||
|
m_idxCitrix = AddIconToImageList(IDI_WORLD);
|
||
|
m_idxServer = AddIconToImageList(IDI_SERVER);
|
||
|
m_idxConsole = AddIconToImageList(IDI_CONSOLE);
|
||
|
m_idxNet = AddIconToImageList(IDI_NET);
|
||
|
m_idxNotSign = AddIconToImageList(IDI_NOTSIGN);
|
||
|
m_idxQuestion = AddIconToImageList(IDI_QUESTIONMARK);
|
||
|
m_idxUser = AddIconToImageList(IDI_USER);
|
||
|
m_idxAsync = AddIconToImageList(IDI_ASYNC);
|
||
|
m_idxCurrentServer = AddIconToImageList(IDI_CURRENT_SERVER);
|
||
|
m_idxCurrentNet = AddIconToImageList(IDI_CURRENT_NET);
|
||
|
m_idxCurrentConsole = AddIconToImageList(IDI_CURRENT_CONSOLE);
|
||
|
m_idxCurrentAsync = AddIconToImageList(IDI_CURRENT_ASYNC);
|
||
|
m_idxDirectAsync = AddIconToImageList(IDI_DIRECT_ASYNC);
|
||
|
m_idxCurrentDirectAsync = AddIconToImageList(IDI_CURRENT_DIRECT_ASYNC);
|
||
|
m_idxDomain = AddIconToImageList(IDI_DOMAIN);
|
||
|
m_idxCurrentDomain = AddIconToImageList(IDI_CURRENT_DOMAIN);
|
||
|
m_idxDomainNotConnected = AddIconToImageList(IDI_DOMAIN_NOT_CONNECTED);
|
||
|
m_idxServerNotConnected = AddIconToImageList(IDI_SERVER_NOT_CONNECTED);
|
||
|
|
||
|
// Overlay for Servers we can't talk to
|
||
|
m_ImageList.SetOverlayImage(m_idxNotSign, 1);
|
||
|
// Overlay for Servers we are currently gathering information about
|
||
|
m_ImageList.SetOverlayImage(m_idxQuestion, 2);
|
||
|
|
||
|
GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL);
|
||
|
|
||
|
} // end CAdminTreeView::BuildImageList
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::DetermineWinStationText
|
||
|
//
|
||
|
// determines the appropriate text to display for
|
||
|
// a WinStation in the tree
|
||
|
//
|
||
|
void CAdminTreeView::DetermineWinStationText(CWinStation *pWinStation, TCHAR *NameToDisplay)
|
||
|
{
|
||
|
ASSERT(pWinStation);
|
||
|
ASSERT(NameToDisplay);
|
||
|
|
||
|
CString NameString;
|
||
|
const TCHAR *pState = StrConnectState(pWinStation->GetState(), FALSE);
|
||
|
|
||
|
switch(pWinStation->GetState()) {
|
||
|
case State_Active: // user logged on to WinStation
|
||
|
case State_Connected: // WinStation connected to client
|
||
|
case State_ConnectQuery: // in the process of connecting to client
|
||
|
case State_Shadow: // shadowing another WinStation
|
||
|
if(wcslen(pWinStation->GetUserName())) {
|
||
|
NameString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName());
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( pWinStation->GetState() == State_ConnectQuery )
|
||
|
{
|
||
|
CString ConnQ;
|
||
|
ConnQ.LoadString( IDS_CONNQ );
|
||
|
|
||
|
wcscpy( NameToDisplay , ConnQ );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wcscpy(NameToDisplay, pWinStation->GetName());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case State_Disconnected: // WinStation logged on without client
|
||
|
if(wcslen(pWinStation->GetUserName())) {
|
||
|
NameString.Format(TEXT("%s (%s)"), pState, pWinStation->GetUserName());
|
||
|
}
|
||
|
else NameString.Format(TEXT("%s (%lu)"), pState, pWinStation->GetLogonId());
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
break;
|
||
|
case State_Idle: // waiting for client to connect
|
||
|
if(pWinStation->GetServer()->GetCTXVersionNum() < 0x200) {
|
||
|
NameString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pState);
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
} else {
|
||
|
NameString.Format(TEXT("%s (%lu)"), pState, pWinStation->GetLogonId());
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
}
|
||
|
break;
|
||
|
case State_Down: // WinStation is down due to error
|
||
|
NameString.Format(TEXT("%s (%lu)"), pState, pWinStation->GetLogonId());
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
break;
|
||
|
case State_Listen: // WinStation is listening for connection
|
||
|
{
|
||
|
CString ListenString;
|
||
|
ListenString.LoadString(IDS_LISTENER);
|
||
|
NameString.Format(TEXT("%s (%s)"), pWinStation->GetName(), ListenString);
|
||
|
wcscpy(NameToDisplay, NameString);
|
||
|
}
|
||
|
break;
|
||
|
case State_Reset: // WinStation is being reset
|
||
|
case State_Init: // WinStation in initialization
|
||
|
wcscpy(NameToDisplay, pWinStation->GetName());
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} // end CAdminTreeView::DetermineWinStationText
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::DetermineWinStationIcon
|
||
|
//
|
||
|
// determines which icon to display for a WinStation
|
||
|
// in the tree
|
||
|
//
|
||
|
int CAdminTreeView::DetermineWinStationIcon(CWinStation *pWinStation)
|
||
|
{
|
||
|
ASSERT(pWinStation);
|
||
|
|
||
|
int WhichIcon = m_idxBlank;
|
||
|
BOOL CurrentWinStation = pWinStation->IsCurrentWinStation();
|
||
|
|
||
|
if(pWinStation->GetState() != State_Disconnected
|
||
|
&& pWinStation->GetState() != State_Idle) {
|
||
|
switch(pWinStation->GetSdClass()) {
|
||
|
case SdAsync:
|
||
|
if(pWinStation->IsDirectAsync())
|
||
|
WhichIcon = CurrentWinStation ? m_idxCurrentDirectAsync : m_idxDirectAsync;
|
||
|
else
|
||
|
WhichIcon = CurrentWinStation ? m_idxCurrentAsync : m_idxAsync;
|
||
|
break;
|
||
|
|
||
|
case SdNetwork:
|
||
|
WhichIcon = CurrentWinStation ? m_idxCurrentNet : m_idxNet;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
WhichIcon = CurrentWinStation ? m_idxCurrentConsole : m_idxConsole;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return WhichIcon;
|
||
|
|
||
|
} // end CAdminTreeView::DetermineWinStationIcon
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::DetermineDomainIcon
|
||
|
//
|
||
|
// determines which icon to display for a Domain
|
||
|
// in the tree
|
||
|
//
|
||
|
int CAdminTreeView::DetermineDomainIcon(CDomain *pDomain)
|
||
|
{
|
||
|
ASSERT(pDomain);
|
||
|
|
||
|
int WhichIcon = m_idxDomain;
|
||
|
|
||
|
if(pDomain->IsCurrentDomain()) return m_idxCurrentDomain;
|
||
|
|
||
|
if(pDomain->GetState() != DS_ENUMERATING && pDomain->GetState() != DS_INITIAL_ENUMERATION)
|
||
|
WhichIcon = m_idxDomainNotConnected;
|
||
|
|
||
|
return WhichIcon;
|
||
|
|
||
|
} // end CAdminTreeView::DetermineDomainIcon
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::DetermineServerIcon
|
||
|
//
|
||
|
// determines which icon to display for a Server
|
||
|
// in the tree
|
||
|
//
|
||
|
int CAdminTreeView::DetermineServerIcon(CServer *pServer)
|
||
|
{
|
||
|
ASSERT(pServer);
|
||
|
|
||
|
int WhichIcon = m_idxServer;
|
||
|
|
||
|
// Is this the current server?
|
||
|
if(pServer->IsCurrentServer()) {
|
||
|
if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
|
||
|
WhichIcon = m_idxServerNotConnected;
|
||
|
else
|
||
|
WhichIcon = m_idxCurrentServer;
|
||
|
} else { // not the current server
|
||
|
if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
|
||
|
WhichIcon = m_idxServerNotConnected;
|
||
|
}
|
||
|
|
||
|
return WhichIcon;
|
||
|
|
||
|
} // end CAdminTreeView::DetermineServerIcon
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::AddServerChildren
|
||
|
//
|
||
|
// Adds the WinStations attached to a given Server
|
||
|
// to the tree
|
||
|
//
|
||
|
void CAdminTreeView::AddServerChildren(HTREEITEM hServer, CServer *pServer , NODETYPE nt)
|
||
|
{
|
||
|
ASSERT(hServer);
|
||
|
ASSERT(pServer);
|
||
|
|
||
|
if(pServer->IsServerSane()) {
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
HTREEITEM hLastNode = hServer;
|
||
|
|
||
|
pServer->LockWinStationList();
|
||
|
|
||
|
// Get a pointer to the server's list of WinStations
|
||
|
CObList *pWinStationList = pServer->GetWinStationList();
|
||
|
|
||
|
// Iterate through the WinStation list
|
||
|
POSITION pos = pWinStationList->GetHeadPosition();
|
||
|
|
||
|
while(pos)
|
||
|
{
|
||
|
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
|
||
|
|
||
|
// Figure out which icon to use
|
||
|
int WhichIcon = DetermineWinStationIcon(pWinStation);
|
||
|
|
||
|
// Figure out what text to display
|
||
|
TCHAR NameToDisplay[128];
|
||
|
DetermineWinStationText(pWinStation, NameToDisplay);
|
||
|
|
||
|
CTreeNode *pNode = new CTreeNode(NODE_WINSTATION, pWinStation);
|
||
|
|
||
|
if( pNode != NULL )
|
||
|
{
|
||
|
pNode->SetSortOrder(pWinStation->GetSortOrder());
|
||
|
|
||
|
hLastNode = AddItemToTree(hServer, NameToDisplay, hLastNode, WhichIcon, (LPARAM)pNode);
|
||
|
|
||
|
if( hLastNode == NULL )
|
||
|
{
|
||
|
delete pNode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// The WinStation wants to know his tree item handle
|
||
|
|
||
|
if( nt == NODE_FAV_LIST )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForFav(hLastNode);
|
||
|
}
|
||
|
else if( nt == NODE_SERVER )
|
||
|
{
|
||
|
pWinStation->SetTreeItem(hLastNode);
|
||
|
}
|
||
|
else if( nt == NODE_THIS_COMP )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForThisComputer( hLastNode );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pServer->UnlockWinStationList();
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
} // end if(pServer->IsServerSane())
|
||
|
|
||
|
|
||
|
} // end CAdminTreeView::AddServerChildren
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////
|
||
|
// F'N: CAdminTreeView::AddDomainToTree
|
||
|
//
|
||
|
// Adds a domain to the tree
|
||
|
//
|
||
|
HTREEITEM CAdminTreeView::AddDomainToTree(CDomain *pDomain)
|
||
|
{
|
||
|
ASSERT(pDomain);
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
HTREEITEM hDomain;
|
||
|
|
||
|
// this points to this computer root
|
||
|
HTREEITEM hR2 = GetTreeCtrl().GetRootItem();
|
||
|
|
||
|
// this points to favorite list
|
||
|
hR2 = GetTreeCtrl().GetNextItem( hR2 , TVGN_NEXT );
|
||
|
|
||
|
// this points to All servers
|
||
|
HTREEITEM hRoot = GetTreeCtrl().GetNextItem( hR2 , TVGN_NEXT );
|
||
|
// Add the domain to the tree
|
||
|
// Create a CTreeNode object with info about this tree node
|
||
|
CTreeNode* pNode = new CTreeNode(NODE_DOMAIN, pDomain);
|
||
|
if(pNode) {
|
||
|
hDomain = AddItemToTree(hRoot, pDomain->GetName(), TVI_SORT, DetermineDomainIcon(pDomain), (LPARAM)pNode);
|
||
|
if(!hDomain) delete pNode;
|
||
|
// Change the icon/overlay for the domain
|
||
|
if(pDomain->GetState() == DS_INITIAL_ENUMERATION)
|
||
|
GetTreeCtrl().SetItemState(hDomain, STATE_QUESTION, 0x0F00);
|
||
|
|
||
|
// The domain wants to know his tree item handle
|
||
|
pDomain->SetTreeItem(hDomain);
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return(hDomain);
|
||
|
|
||
|
} // end CAdminTreeView::AddDomainToTree
|
||
|
|
||
|
|
||
|
//////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminViewsReady
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminViewsReady(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get a pointer to our document
|
||
|
CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
|
||
|
|
||
|
// We want to remember the tree item of the current server for later
|
||
|
HTREEITEM hCurrentServer = NULL;
|
||
|
|
||
|
HTREEITEM hThisComputerRootItem = NULL;
|
||
|
HTREEITEM hThisComputer = NULL;
|
||
|
HTREEITEM hFavRoot = NULL;
|
||
|
|
||
|
// add enum for fav node
|
||
|
CString cstrThisComputer;
|
||
|
CString cstrFavSrv;
|
||
|
|
||
|
CNodeType *pNodeType = new CNodeType( NODE_THIS_COMP );
|
||
|
|
||
|
// ok to pass in null
|
||
|
|
||
|
CTreeNode *pThisComp = new CTreeNode( NODE_THIS_COMP , pNodeType );
|
||
|
|
||
|
if( pThisComp != NULL )
|
||
|
{
|
||
|
cstrThisComputer.LoadString( IDS_THISCOMPUTER );
|
||
|
|
||
|
hThisComputerRootItem = AddItemToTree( NULL , cstrThisComputer , TVI_ROOT , m_idxDomain , ( LPARAM )pThisComp );
|
||
|
}
|
||
|
|
||
|
// ok to overrun
|
||
|
|
||
|
pNodeType = new CNodeType( NODE_FAV_LIST );
|
||
|
|
||
|
// it's ok to pass null here
|
||
|
|
||
|
CTreeNode *pFavNode = new CTreeNode( NODE_FAV_LIST , pNodeType );
|
||
|
|
||
|
if( pFavNode != NULL )
|
||
|
{
|
||
|
cstrFavSrv.LoadString( IDS_FAVSERVERS );
|
||
|
|
||
|
hFavRoot = AddItemToTree( NULL , cstrFavSrv , TVI_ROOT , m_idxCitrix, ( LPARAM )pFavNode );
|
||
|
}
|
||
|
|
||
|
// add the root to the tree
|
||
|
CString citrix;
|
||
|
citrix.LoadString(IDS_TREEROOT);
|
||
|
CTreeNode* pRootNode = new CTreeNode(NODE_ALL_SERVERS, NULL);
|
||
|
if(!pRootNode) {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HTREEITEM hRoot = AddItemToTree(NULL, citrix, TVI_ROOT, m_idxCitrix, (LPARAM)pRootNode);
|
||
|
|
||
|
if(!hRoot) delete pRootNode;
|
||
|
|
||
|
// set up some 'placeholder'-style vars
|
||
|
HTREEITEM hCurrParent = hRoot;
|
||
|
HTREEITEM hLastConnection = hRoot;
|
||
|
HTREEITEM hLastNode = hRoot;
|
||
|
HTREEITEM hDomain = NULL;
|
||
|
|
||
|
// Get a pointer to the list of domains
|
||
|
CObList *pDomainList = doc->GetDomainList();
|
||
|
POSITION dpos = pDomainList->GetHeadPosition();
|
||
|
|
||
|
while(dpos) {
|
||
|
CDomain *pDomain = (CDomain*)pDomainList->GetNext(dpos);
|
||
|
AddDomainToTree(pDomain);
|
||
|
}
|
||
|
|
||
|
// Get a pointer to the list of servers
|
||
|
doc->LockServerList();
|
||
|
CObList *pServerList = doc->GetServerList();
|
||
|
|
||
|
// Iterate through the server list
|
||
|
POSITION pos = pServerList->GetHeadPosition();
|
||
|
|
||
|
CServer *pCurrentServer;
|
||
|
|
||
|
while(pos) {
|
||
|
// Go to the next server in the list
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
|
||
|
if( pServer == NULL )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// If this Server's domain isn't in the tree, add it
|
||
|
CDomain *pDomain = pServer->GetDomain();
|
||
|
if(pDomain != NULL )
|
||
|
{
|
||
|
hDomain = pDomain->GetTreeItem();
|
||
|
ASSERT(hDomain);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// server is not in a domain
|
||
|
hDomain = hRoot;
|
||
|
}
|
||
|
|
||
|
// Add the server to the tree
|
||
|
// Create a CTreeNode object with info about this tree node
|
||
|
CTreeNode* pNode = new CTreeNode(NODE_SERVER, pServer);
|
||
|
if(pNode) {
|
||
|
|
||
|
if( !pServer->IsCurrentServer() )
|
||
|
{
|
||
|
// If the server is the current server, use a different icon
|
||
|
hLastConnection = AddItemToTree(hDomain,
|
||
|
pServer->GetName(),
|
||
|
hLastConnection,
|
||
|
DetermineServerIcon(pServer),
|
||
|
(LPARAM)pNode);
|
||
|
if(!hLastConnection) delete pNode;
|
||
|
// The server wants to know his tree item handle
|
||
|
pServer->SetTreeItem(hLastConnection);
|
||
|
// If the server isn't sane, put a not sign over the icon
|
||
|
if(!pServer->IsServerSane()) GetTreeCtrl().SetItemState(hLastConnection, STATE_NOT, 0x0F00);
|
||
|
// If we aren't done getting all the information about this server,
|
||
|
// put a question mark over the icon
|
||
|
else if(pServer->IsState(SS_GETTING_INFO)) GetTreeCtrl().SetItemState(hLastConnection, STATE_QUESTION, 0x0F00);
|
||
|
|
||
|
AddServerChildren(hLastConnection, pServer , NODE_SERVER );
|
||
|
}
|
||
|
|
||
|
// Remember if this is the current server
|
||
|
else
|
||
|
{
|
||
|
hCurrentServer = hLastConnection;
|
||
|
|
||
|
/* Add this item under the this computer root */
|
||
|
|
||
|
hThisComputer = AddItemToTree( hThisComputerRootItem ,
|
||
|
pServer->GetName() ,
|
||
|
TVI_FIRST ,
|
||
|
DetermineServerIcon(pServer),
|
||
|
(LPARAM)pNode );
|
||
|
|
||
|
CTreeNode* pItem = new CTreeNode(NODE_SERVER, pServer);
|
||
|
|
||
|
// uncomment this line if you want this computer to be part of the domain tree list
|
||
|
/*
|
||
|
hLastConnection = AddItemToTree( hDomain,
|
||
|
pServer->GetName(),
|
||
|
hLastConnection,
|
||
|
DetermineServerIcon(pServer),
|
||
|
(LPARAM)pItem);
|
||
|
*/
|
||
|
|
||
|
pServer->SetTreeItemForThisComputer( hThisComputer );
|
||
|
|
||
|
// uncomment this line if you want this computer to be part of the domain tree list
|
||
|
// pServer->SetTreeItem( hLastConnection );
|
||
|
|
||
|
if( !pServer->IsServerSane() )
|
||
|
{
|
||
|
GetTreeCtrl().SetItemState(hThisComputer, STATE_NOT, 0x0F00);
|
||
|
// uncomment this line if you want this computer to be part of the domain tree list
|
||
|
// GetTreeCtrl().SetItemState(hLastConnection, STATE_NOT, 0x0F00);
|
||
|
}
|
||
|
|
||
|
// uncomment this line if you want this computer to be part of the domain tree list
|
||
|
// AddServerChildren( hLastConnection, pServer , NODE_SERVER );
|
||
|
|
||
|
AddServerChildren( hThisComputer , pServer , NODE_SERVER );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
} // end while(pos)
|
||
|
|
||
|
doc->UnlockServerList();
|
||
|
|
||
|
// We want to show the main server in this computer node
|
||
|
|
||
|
//GetTreeCtrl().Expand(hRoot, TVE_EXPAND);
|
||
|
|
||
|
GetTreeCtrl().Expand( hThisComputerRootItem , TVE_COLLAPSE );
|
||
|
|
||
|
/*
|
||
|
LRESULT lResult = 0xc0;
|
||
|
// We want to default to having the current server being the
|
||
|
// currently selected item in the tree and be expanded
|
||
|
|
||
|
if( hThisComputerRootItem != NULL && ( g_dwTreeViewExpandedStates & TV_THISCOMP ) )
|
||
|
{
|
||
|
if( hThisComputer != NULL )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem(hThisComputer);
|
||
|
GetTreeCtrl().Expand(hThisComputer, TVE_EXPAND);
|
||
|
// GetTreeCtrl().Expand(hDomain, TVE_EXPAND);
|
||
|
//lResult = 0xc0;
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( hFavRoot != NULL && ( g_dwTreeViewExpandedStates & TV_FAVS ) )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem( hFavRoot );
|
||
|
GetTreeCtrl().Expand( hFavRoot , TVE_EXPAND );
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
|
||
|
if( hRoot != NULL && ( g_dwTreeViewExpandedStates & TV_ALLSERVERS ) )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem( hRoot );
|
||
|
GetTreeCtrl().Expand( hRoot , TVE_EXPAND );
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminViewsReady
|
||
|
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminAddServer
|
||
|
//
|
||
|
// Message Handler to add a Server to the tree
|
||
|
// Pointer to CServer to add is in lParam
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminAddServer(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
CServer *pServer = (CServer*)lParam;
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
// If this Server's domain isn't in the tree, add it
|
||
|
HTREEITEM hDomain = NULL;
|
||
|
CDomain *pDomain = pServer->GetDomain();
|
||
|
if(pDomain) {
|
||
|
hDomain = pDomain->GetTreeItem();
|
||
|
ASSERT(hDomain);
|
||
|
} else {
|
||
|
// server is not in a domain
|
||
|
hDomain = tree.GetRootItem();
|
||
|
}
|
||
|
|
||
|
// First make sure the server isn't already in the tree
|
||
|
// Get the first server under the domain
|
||
|
HTREEITEM hItem = tree.GetNextItem(hDomain, TVGN_CHILD);
|
||
|
while(hItem) {
|
||
|
// Get the data attached to the tree item
|
||
|
CTreeNode *node = (CTreeNode*)tree.GetItemData(hItem);
|
||
|
if(node) {
|
||
|
// Is this the server we want to add
|
||
|
CServer *pServer = (CServer*)node->GetTreeObject();
|
||
|
if(pServer == (CServer*)lParam) {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
hItem = tree.GetNextItem(hItem, TVGN_NEXT);
|
||
|
}
|
||
|
|
||
|
// Add the server to the tree
|
||
|
// Create a CTreeNode object with info about this tree node
|
||
|
CTreeNode* pNode = new CTreeNode(NODE_SERVER, pServer);
|
||
|
if(pNode)
|
||
|
{
|
||
|
// If the server is the current server, use a different icon
|
||
|
|
||
|
HTREEITEM hServer = AddItemToTree(hDomain, pServer->GetName(), (HTREEITEM)wParam,
|
||
|
DetermineServerIcon(pServer), (LPARAM)pNode);
|
||
|
if( !hServer )
|
||
|
{
|
||
|
delete pNode;
|
||
|
}
|
||
|
// The server wants to know his tree item handle
|
||
|
pServer->SetTreeItem(hServer);
|
||
|
// If the server isn't sane, put a not sign over the icon
|
||
|
if( !pServer->IsServerSane() )
|
||
|
{
|
||
|
tree.SetItemState(hServer, STATE_NOT, 0x0F00);
|
||
|
}
|
||
|
// If we aren't done getting all the information about this server,
|
||
|
// put a question mark over the icon
|
||
|
else if(pServer->IsState(SS_GETTING_INFO))
|
||
|
{
|
||
|
tree.SetItemState(hServer, STATE_QUESTION, 0x0F00);
|
||
|
}
|
||
|
|
||
|
AddServerChildren(hServer, pServer , NODE_SERVER );
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminAddServer
|
||
|
|
||
|
//----------------------------------------------------------------------
|
||
|
// ok if you traced me to here you are almost there
|
||
|
// 1) now we need to update the server item and place it under the favorites
|
||
|
// folder
|
||
|
// 2) inform the server child items that it will have a new parent
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminAddServerToFavs( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
CServer *pServer = ( CServer* )lp;
|
||
|
|
||
|
if( pServer == NULL )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnAdminAddServerToFavs invalid arg\n");
|
||
|
return ( LRESULT )-1;
|
||
|
}
|
||
|
|
||
|
LockTreeControl( );
|
||
|
|
||
|
if( pServer->IsServerInactive() || pServer->IsState( SS_DISCONNECTING ) )
|
||
|
{
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
HTREEITEM hFavs = GetTreeCtrl().GetRootItem( );
|
||
|
HTREEITEM hItem;
|
||
|
|
||
|
hFavs = tree.GetNextItem( hFavs , TVGN_NEXT );
|
||
|
|
||
|
hItem = tree.GetNextItem( hFavs , TVGN_CHILD );
|
||
|
|
||
|
|
||
|
// check for duplicate entry
|
||
|
|
||
|
while( hItem != NULL )
|
||
|
{
|
||
|
// Get the data attached to the tree item
|
||
|
CTreeNode *pTreenode = (CTreeNode*)tree.GetItemData( hItem );
|
||
|
|
||
|
if( pTreenode != NULL )
|
||
|
{
|
||
|
// Is this the server we want to add
|
||
|
CServer *pSvr = (CServer*)pTreenode->GetTreeObject();
|
||
|
|
||
|
if( pSvr == pServer )
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hItem = tree.GetNextItem(hItem, TVGN_NEXT);
|
||
|
}
|
||
|
|
||
|
CTreeNode* pNode = new CTreeNode(NODE_SERVER, pServer);
|
||
|
|
||
|
if( pNode != NULL )
|
||
|
{
|
||
|
HTREEITEM hServer = AddItemToTree( hFavs,
|
||
|
pServer->GetName(),
|
||
|
TVI_SORT,
|
||
|
DetermineServerIcon(pServer),
|
||
|
(LPARAM)pNode);
|
||
|
|
||
|
|
||
|
if( hServer == NULL )
|
||
|
{
|
||
|
delete pNode;
|
||
|
}
|
||
|
|
||
|
// The server wants to know his tree item handle
|
||
|
pServer->SetTreeItemForFav( hServer );
|
||
|
|
||
|
// If the server isn't sane, put a not sign over the icon
|
||
|
if( !pServer->IsServerSane() )
|
||
|
{
|
||
|
tree.SetItemState(hServer, STATE_NOT, 0x0F00);
|
||
|
}
|
||
|
// If we aren't done getting all the information about this server,
|
||
|
// put a question mark over the icon
|
||
|
else if( pServer->IsState( SS_GETTING_INFO ) )
|
||
|
{
|
||
|
tree.SetItemState(hServer, STATE_QUESTION, 0x0F00);
|
||
|
}
|
||
|
|
||
|
AddServerChildren( hServer , pServer , NODE_FAV_LIST );
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
tree.Invalidate( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
//=----------------------------------------------------------------------------------
|
||
|
LRESULT CAdminTreeView::OnAdminRemoveServerFromFavs( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
LockTreeControl();
|
||
|
|
||
|
CServer *pServer = ( CServer* )lp;
|
||
|
|
||
|
DBGMSG( L"CAdminTreeView::OnAdminRemoveServerFromFavs -- %s\n" , pServer->GetName( ) );
|
||
|
|
||
|
HTREEITEM hFavServer = pServer->GetTreeItemFromFav();
|
||
|
|
||
|
#ifdef _STRESS_BUILD
|
||
|
DBGMSG( L"Handle to hFavServer 0x%x\n" , hFavServer );
|
||
|
#endif
|
||
|
|
||
|
if( hFavServer == NULL )
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
|
||
|
|
||
|
CTreeNode *pNode = (CTreeNode*)GetTreeCtrl().GetItemData( hFavServer );
|
||
|
|
||
|
if( pNode != NULL && pNode->GetNodeType( ) == NODE_SERVER )
|
||
|
{
|
||
|
// Is this the server we want to update
|
||
|
CServer *pTreeServer = ( CServer* )pNode->GetTreeObject();
|
||
|
|
||
|
if( pTreeServer != pServer)
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Loop through it's children and delete their data
|
||
|
|
||
|
pServer->LockWinStationList( );
|
||
|
|
||
|
HTREEITEM hChild = GetTreeCtrl().GetNextItem( hFavServer , TVGN_CHILD );
|
||
|
|
||
|
while( hChild != NULL )
|
||
|
{
|
||
|
CTreeNode *pChildNode = ( CTreeNode* )GetTreeCtrl().GetItemData( hChild );
|
||
|
|
||
|
if( pChildNode != NULL && pChildNode->GetNodeType( ) == NODE_WINSTATION )
|
||
|
{
|
||
|
// Tell the WinStation it is no longer in the tree
|
||
|
CWinStation *pWinStation = ( CWinStation* )pChildNode->GetTreeObject();
|
||
|
|
||
|
if( pWinStation != NULL )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForFav(NULL);
|
||
|
}
|
||
|
|
||
|
delete pChildNode;
|
||
|
}
|
||
|
|
||
|
hChild = GetTreeCtrl().GetNextItem( hChild , TVGN_NEXT );
|
||
|
}
|
||
|
|
||
|
// Delete the data attached to the tree item
|
||
|
delete pNode;
|
||
|
|
||
|
// Let the server know he is no longer in the tree
|
||
|
pServer->SetTreeItemForFav(NULL);
|
||
|
|
||
|
GetTreeCtrl().DeleteItem( hFavServer );
|
||
|
|
||
|
pServer->UnlockWinStationList( );
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminRemoveServer
|
||
|
//
|
||
|
// Message Handler to remove a Server from the tree
|
||
|
// Pointer to CServer of server to remove is in lParam
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminRemoveServer(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
CServer *pServer = (CServer*)lParam;
|
||
|
|
||
|
HTREEITEM hServer = pServer->GetTreeItem();
|
||
|
if(!hServer) return 0;
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hServer);
|
||
|
if(node) {
|
||
|
// Is this the server we want to update
|
||
|
CServer *pTreeServer = (CServer*)node->GetTreeObject();
|
||
|
// Make sure the tree node is correct
|
||
|
if(pTreeServer != pServer) {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Loop through it's children and delete their data
|
||
|
HTREEITEM hChild = GetTreeCtrl().GetNextItem(hServer, TVGN_CHILD);
|
||
|
while(hChild) {
|
||
|
CTreeNode *ChildNode = (CTreeNode*)GetTreeCtrl().GetItemData(hChild);
|
||
|
if(ChildNode) {
|
||
|
// Tell the WinStation it is no longer in the tree
|
||
|
CWinStation *pWinStation = (CWinStation*)ChildNode->GetTreeObject();
|
||
|
if(pWinStation)
|
||
|
pWinStation->SetTreeItem(NULL);
|
||
|
delete ChildNode;
|
||
|
}
|
||
|
hChild = GetTreeCtrl().GetNextItem(hChild, TVGN_NEXT);
|
||
|
}
|
||
|
|
||
|
// Delete the data attached to the tree item
|
||
|
delete node;
|
||
|
// Let the server know he is no longer in the tree
|
||
|
pServer->SetTreeItem(NULL);
|
||
|
// Remove the server from the tree
|
||
|
// This SHOULD remove all it's children
|
||
|
GetTreeCtrl().DeleteItem(hServer);
|
||
|
|
||
|
|
||
|
// TODO
|
||
|
// if this means that CServer does not exist we need to remove this from the favorite list
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminRemoveServer
|
||
|
|
||
|
|
||
|
/*=--------------------------------------------------------------------------------------
|
||
|
OnAdminUpdateServer
|
||
|
|
||
|
Message handler to update a Server in the tree
|
||
|
Pointer to CServer to update is in lParam
|
||
|
|
||
|
Updates server item in favorites folder
|
||
|
and if server item is this computer it gets updated as well.
|
||
|
|
||
|
*=------------------------------------------------------------------------------------*/
|
||
|
LRESULT CAdminTreeView::OnAdminUpdateServer(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
LockTreeControl( );
|
||
|
// If favorite folders is expanded don't forget to update the tree item
|
||
|
|
||
|
CServer *pServer = (CServer*)lParam;
|
||
|
|
||
|
HTREEITEM hServer = pServer->GetTreeItem();
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
UpdateServerTreeNodeState( hServer , pServer , NODE_SERVER );
|
||
|
}
|
||
|
|
||
|
hServer = pServer->GetTreeItemFromFav( );
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
UpdateServerTreeNodeState( hServer , pServer , NODE_FAV_LIST );
|
||
|
}
|
||
|
|
||
|
hServer = pServer->GetTreeItemFromThisComputer( );
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
UpdateServerTreeNodeState( hServer , pServer , NODE_THIS_COMP );
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*=--------------------------------------------------------------------------------------
|
||
|
|
||
|
UpdateServerTreeNodeState
|
||
|
|
||
|
hServer -- tree item that needs updating
|
||
|
pServer -- server object
|
||
|
|
||
|
*=------------------------------------------------------------------------------------*/
|
||
|
LRESULT CAdminTreeView::UpdateServerTreeNodeState( HTREEITEM hServer , CServer *pServer , NODETYPE nt )
|
||
|
{
|
||
|
LockTreeControl( );
|
||
|
|
||
|
if( hServer == NULL )
|
||
|
{
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
|
||
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hServer);
|
||
|
if( node != NULL && node->GetNodeType( ) == NODE_SERVER )
|
||
|
{
|
||
|
// Is this the server we want to update
|
||
|
CServer *pTreeServer = (CServer*)node->GetTreeObject();
|
||
|
// Make sure the tree node is correct
|
||
|
if(pTreeServer != pServer)
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
UINT NewState;
|
||
|
// Remember the previous state
|
||
|
UINT PreviousState = GetTreeCtrl().GetItemState(hServer, 0x0F00);
|
||
|
// Change the icon/overlay for the server
|
||
|
// If the server isn't sane, put a not sign over the icon
|
||
|
if(!pServer->IsServerSane()) NewState = STATE_NOT;
|
||
|
// If we aren't done getting all the information about this server,
|
||
|
// put a question mark over the icon
|
||
|
else if(pServer->IsState(SS_GETTING_INFO)) NewState = STATE_QUESTION;
|
||
|
// If it is fine, we want to remove any overlays from the icon
|
||
|
else NewState = STATE_NORMAL;
|
||
|
|
||
|
// Set the tree item to the new state
|
||
|
GetTreeCtrl().SetItemState(hServer, NewState, 0x0F00);
|
||
|
|
||
|
// If this Server was not opened and now is GOOD,
|
||
|
// add it's children to the tree
|
||
|
if(PreviousState != STATE_NORMAL && pServer->IsState(SS_GOOD)) {
|
||
|
int ServerIcon = DetermineServerIcon(pServer);
|
||
|
GetTreeCtrl().SetItemImage(hServer, ServerIcon, ServerIcon);
|
||
|
AddServerChildren(hServer, pServer , nt );
|
||
|
// If this server is the server the user is sitting at and is
|
||
|
// the currently selected tree item, expand it
|
||
|
if(hServer == GetTreeCtrl().GetSelectedItem() && pServer->IsCurrentServer()) {
|
||
|
GetTreeCtrl().Expand(hServer, TVE_EXPAND);
|
||
|
}
|
||
|
}
|
||
|
else if(pServer->GetPreviousState() == SS_DISCONNECTING && pServer->IsState(SS_NOT_CONNECTED)) {
|
||
|
int ServerIcon = DetermineServerIcon(pServer);
|
||
|
GetTreeCtrl().SetItemImage(hServer, ServerIcon, ServerIcon);
|
||
|
}
|
||
|
|
||
|
// If we changed the state of this server and it is the currently
|
||
|
// selected node in the tree, we need to send a message to change
|
||
|
// the view
|
||
|
if(NewState != PreviousState && hServer == GetTreeCtrl().GetSelectedItem()) {
|
||
|
ForceSelChange();
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminUpdateServer
|
||
|
|
||
|
|
||
|
LRESULT CAdminTreeView::OnAdminAddWinStation(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
ODS( L"**CAdminTreeView::OnAdminAddWinStation\n" );
|
||
|
|
||
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
||
|
|
||
|
|
||
|
// Get the HTREEITEM of the Server this WinStation is attached to
|
||
|
// TODO:
|
||
|
// update the server item in the favorite list
|
||
|
|
||
|
HTREEITEM hServer = pWinStation->GetServer()->GetTreeItem();
|
||
|
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
AddWinStation( pWinStation , hServer , ( BOOL )wParam , NODE_NONE );
|
||
|
}
|
||
|
|
||
|
hServer = pWinStation->GetServer( )->GetTreeItemFromFav( );
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
AddWinStation( pWinStation , hServer , ( BOOL )wParam , NODE_FAV_LIST );
|
||
|
}
|
||
|
|
||
|
hServer = pWinStation->GetServer( )->GetTreeItemFromThisComputer( );
|
||
|
|
||
|
if( hServer != NULL )
|
||
|
{
|
||
|
AddWinStation( pWinStation , hServer , ( BOOL )wParam , NODE_THIS_COMP );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminAddWinStation
|
||
|
//
|
||
|
// Message handler to add a WinStation to the tree
|
||
|
// lParam = pointer to CWinStation to add
|
||
|
// wParam is TRUE if this is replacing a WinStation that was currently selected
|
||
|
//
|
||
|
LRESULT CAdminTreeView::AddWinStation( CWinStation * pWinStation , HTREEITEM hServer , BOOL bSel , NODETYPE nt )
|
||
|
{
|
||
|
ODS( L"**CAdminTreeView::AddWinStation\n" );
|
||
|
|
||
|
HTREEITEM hWinStation;
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Figure out which icon to use
|
||
|
int WhichIcon = DetermineWinStationIcon(pWinStation);
|
||
|
|
||
|
// Figure out what text to display
|
||
|
TCHAR NameToDisplay[128];
|
||
|
DetermineWinStationText(pWinStation, NameToDisplay);
|
||
|
|
||
|
CTreeNode *pNode = new CTreeNode(NODE_WINSTATION, pWinStation);
|
||
|
if(pNode) {
|
||
|
pNode->SetSortOrder(pWinStation->GetSortOrder());
|
||
|
|
||
|
// We have to insert this WinStation in sorted order
|
||
|
// Get the first WinStation item attached to this server
|
||
|
HTREEITEM hChild = GetTreeCtrl().GetNextItem(hServer, TVGN_CHILD);
|
||
|
HTREEITEM hLastChild = TVI_FIRST;
|
||
|
BOOL bAdded = FALSE;
|
||
|
|
||
|
while(hChild)
|
||
|
{
|
||
|
CTreeNode *ChildNode = (CTreeNode*)GetTreeCtrl().GetItemData(hChild);
|
||
|
if(ChildNode)
|
||
|
{
|
||
|
// Does it belong before this tree node?
|
||
|
CWinStation *pTreeWinStation = (CWinStation*)ChildNode->GetTreeObject();
|
||
|
if((pTreeWinStation->GetSortOrder() > pWinStation->GetSortOrder())
|
||
|
|| ((pTreeWinStation->GetSortOrder() == pWinStation->GetSortOrder()) &&
|
||
|
(pTreeWinStation->GetSdClass() > pWinStation->GetSdClass())))
|
||
|
{
|
||
|
hWinStation = AddItemToTree(hServer, NameToDisplay, hLastChild, WhichIcon, (LPARAM)pNode);
|
||
|
|
||
|
if(!hWinStation)
|
||
|
{
|
||
|
delete pNode;
|
||
|
}
|
||
|
|
||
|
// The WinStation wants to know his tree item handle
|
||
|
|
||
|
if( nt == NODE_FAV_LIST )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForFav( hWinStation );
|
||
|
}
|
||
|
else if( nt == NODE_THIS_COMP )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForThisComputer( hWinStation );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pWinStation->SetTreeItem(hWinStation);
|
||
|
}
|
||
|
|
||
|
bAdded = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
hLastChild = hChild;
|
||
|
hChild = GetTreeCtrl().GetNextItem(hChild, TVGN_NEXT);
|
||
|
}
|
||
|
|
||
|
// If we didn't add it yet, add it at the end
|
||
|
if(!bAdded)
|
||
|
{
|
||
|
hWinStation = AddItemToTree(hServer, NameToDisplay, hLastChild, WhichIcon, (LPARAM)pNode);
|
||
|
|
||
|
if( hWinStation == NULL )
|
||
|
{
|
||
|
delete pNode;
|
||
|
}
|
||
|
|
||
|
// The WinStation wants to know his tree item handle
|
||
|
if( nt == NODE_FAV_LIST )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForFav( hWinStation );
|
||
|
}
|
||
|
else if( nt == NODE_THIS_COMP )
|
||
|
{
|
||
|
pWinStation->SetTreeItemForThisComputer( hWinStation );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pWinStation->SetTreeItem(hWinStation);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// If this is replacing a WinStation in the tree that was the currently selected
|
||
|
// tree item, make this new item in the tree the currently selected item
|
||
|
if( bSel ) {
|
||
|
GetTreeCtrl().SelectItem(hWinStation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminAddWinStation
|
||
|
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminUpdateWinStation
|
||
|
//
|
||
|
// Message handler to update a WinStation in the tree
|
||
|
// lParam = pointer to CWinStation to update
|
||
|
//
|
||
|
|
||
|
LRESULT CAdminTreeView::OnAdminUpdateWinStation(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnAdminUpdateWinStation\n" );
|
||
|
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
||
|
|
||
|
|
||
|
HTREEITEM hWinStation = pWinStation->GetTreeItem();
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
UpdateWinStation( hWinStation , pWinStation );
|
||
|
}
|
||
|
|
||
|
hWinStation = pWinStation->GetTreeItemFromFav( );
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
UpdateWinStation( hWinStation , pWinStation );
|
||
|
}
|
||
|
|
||
|
hWinStation = pWinStation->GetTreeItemFromThisComputer( );
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
UpdateWinStation( hWinStation , pWinStation );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LRESULT CAdminTreeView::UpdateWinStation( HTREEITEM hWinStation , CWinStation *pWinStation )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::UpdateWinStation\n" );
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hWinStation);
|
||
|
if(node) {
|
||
|
// Is this the WinStation we want to update
|
||
|
CWinStation *pTreeWinStation = (CWinStation*)node->GetTreeObject();
|
||
|
// Make sure the tree node is correct
|
||
|
if(pTreeWinStation != pWinStation) {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// If the sort order of this WinStation has changed,
|
||
|
// we have to remove it from the tree and add it back in
|
||
|
if(node->GetSortOrder() != pWinStation->GetSortOrder())
|
||
|
{
|
||
|
OnAdminRemoveWinStation( 0 , ( LPARAM )pWinStation );
|
||
|
|
||
|
/*GetTreeCtrl().DeleteItem(hWinStation);
|
||
|
|
||
|
pWinStation->SetTreeItem(NULL);
|
||
|
*/
|
||
|
|
||
|
OnAdminAddWinStation((GetTreeCtrl().GetSelectedItem() == hWinStation), ( LPARAM )pWinStation );
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int WhichIcon = DetermineWinStationIcon(pWinStation);
|
||
|
GetTreeCtrl().SetItemImage(hWinStation, WhichIcon, WhichIcon);
|
||
|
|
||
|
TCHAR NameToDisplay[128];
|
||
|
DetermineWinStationText(pWinStation, NameToDisplay);
|
||
|
GetTreeCtrl().SetItemText(hWinStation, NameToDisplay);
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminUpdateWinStation
|
||
|
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminRemoveWinStation
|
||
|
//
|
||
|
// Message handler to remove a WinStation from the tree
|
||
|
// lParam = pointer to CWinStation to remove
|
||
|
LRESULT CAdminTreeView::OnAdminRemoveWinStation(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnAdminRemoveWinStation\n" );
|
||
|
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
//TODO:
|
||
|
// remove winstaion from favorite list
|
||
|
|
||
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
||
|
|
||
|
HTREEITEM hWinStation;
|
||
|
|
||
|
hWinStation = pWinStation->GetTreeItem();
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
RemoveWinstation( hWinStation , pWinStation );
|
||
|
|
||
|
pWinStation->SetTreeItem( NULL );
|
||
|
}
|
||
|
|
||
|
hWinStation = pWinStation->GetTreeItemFromFav( );
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
RemoveWinstation( hWinStation , pWinStation );
|
||
|
|
||
|
pWinStation->SetTreeItemForFav( NULL );
|
||
|
}
|
||
|
|
||
|
hWinStation = pWinStation->GetTreeItemFromThisComputer( );
|
||
|
|
||
|
if( hWinStation != NULL )
|
||
|
{
|
||
|
RemoveWinstation( hWinStation , pWinStation );
|
||
|
|
||
|
pWinStation->SetTreeItemForThisComputer( NULL );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
LRESULT CAdminTreeView::RemoveWinstation( HTREEITEM hWinStation , CWinStation *pWinStation )
|
||
|
{
|
||
|
BOOL CurrentInTree = FALSE;
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
CTreeNode *node = ( CTreeNode * )GetTreeCtrl().GetItemData(hWinStation);
|
||
|
|
||
|
if( node != NULL )
|
||
|
{
|
||
|
// Is this the WinStation we want to update
|
||
|
CWinStation *pTreeWinStation = (CWinStation*)node->GetTreeObject();
|
||
|
// Make sure the tree node is correct
|
||
|
if(pTreeWinStation != pWinStation)
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Delete the data attached to the tree item
|
||
|
delete node;
|
||
|
// Let the WinStation know he is no longer in the tree
|
||
|
|
||
|
// Is this WinStation currently selected in the tree?
|
||
|
CurrentInTree = ( GetTreeCtrl().GetSelectedItem() == hWinStation );
|
||
|
|
||
|
// Remove the WinStation from the tree
|
||
|
GetTreeCtrl().DeleteItem( hWinStation );
|
||
|
|
||
|
// If this WinStation is the currently selected node in the tree,
|
||
|
// make it not so
|
||
|
// This may not be necessary!
|
||
|
if( CurrentInTree )
|
||
|
{
|
||
|
((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING);
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminRemoveWinStation
|
||
|
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminUpdateDomain
|
||
|
//
|
||
|
// Message handler to update a Domain in the tree
|
||
|
// Pointer to CDomain to update is in lParam
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminUpdateDomain(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
CDomain *pDomain = (CDomain*)lParam;
|
||
|
|
||
|
HTREEITEM hDomain = pDomain->GetTreeItem();
|
||
|
if(!hDomain) return 0;
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get the data attached to this tree node
|
||
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hDomain);
|
||
|
if(node) {
|
||
|
// Is this the domain we want to update
|
||
|
CDomain *pTreeDomain = (CDomain*)node->GetTreeObject();
|
||
|
// Make sure the tree node is correct
|
||
|
if(pTreeDomain != pDomain) {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
UnlockTreeControl();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
UINT NewState;
|
||
|
// Remember the previous state
|
||
|
UINT PreviousState = GetTreeCtrl().GetItemState(hDomain, 0x0F00);
|
||
|
// Change the icon/overlay for the domain
|
||
|
if(pDomain->GetState() == DS_INITIAL_ENUMERATION) NewState = STATE_QUESTION;
|
||
|
// If it is fine, we want to remove any overlays from the icon
|
||
|
else NewState = STATE_NORMAL;
|
||
|
|
||
|
// Set the tree item to the new state
|
||
|
GetTreeCtrl().SetItemState(hDomain, NewState, 0x0F00);
|
||
|
|
||
|
// If the new state is STATE_NORMAL, change the icon
|
||
|
if(NewState == STATE_NORMAL) {
|
||
|
int DomainIcon = DetermineDomainIcon(pDomain);
|
||
|
GetTreeCtrl().SetItemImage(hDomain, DomainIcon, DomainIcon);
|
||
|
}
|
||
|
|
||
|
// If we changed the state of this domain and it is the currently
|
||
|
// selected node in the tree, we need to send a message to change
|
||
|
// the view
|
||
|
if(NewState != PreviousState && hDomain == GetTreeCtrl().GetSelectedItem()) {
|
||
|
ForceSelChange();
|
||
|
}
|
||
|
|
||
|
if(pDomain->GetState() == DS_ENUMERATING) GetTreeCtrl().Expand(hDomain, TVE_EXPAND);
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminUpdateDomain
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnAdminAddDomain
|
||
|
//
|
||
|
// Message handler to update a Domain in the tree
|
||
|
// Pointer to CDomain to update is in lParam
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminAddDomain(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
if(lParam)
|
||
|
{
|
||
|
CDomain *pDomain = (CDomain*)lParam;
|
||
|
return (LRESULT)AddDomainToTree(pDomain);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CAdminTreeView::OnAdminAddDomain
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnContextMenu
|
||
|
//
|
||
|
// Message handler called when user wants a context menu
|
||
|
// This happens when the user clicks the right mouse button,
|
||
|
// presses Shift-F10, or presses the menu key on a Windows keyboard
|
||
|
//
|
||
|
void CAdminTreeView::OnContextMenu(CWnd* pWnd, CPoint ptScreen)
|
||
|
{
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get a pointer to our document
|
||
|
CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
// TODO: Add your message handler code here
|
||
|
HTREEITEM hItem;
|
||
|
CPoint ptClient = ptScreen;
|
||
|
ScreenToClient(&ptClient);
|
||
|
|
||
|
// If we got here from the keyboard,
|
||
|
if(ptScreen.x == -1 && ptScreen.y == -1) {
|
||
|
hItem = tree.GetSelectedItem();
|
||
|
|
||
|
RECT rect;
|
||
|
tree.GetItemRect(hItem, &rect, TRUE);
|
||
|
|
||
|
ptScreen.x = rect.left + (rect.right - rect.left)/2;
|
||
|
ptScreen.y = rect.top + (rect.bottom - rect.top)/2;
|
||
|
|
||
|
tree.ClientToScreen(&ptScreen);
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
// we shouldn't get here from the mouse
|
||
|
// but sometimes we do, so handle it gracefully
|
||
|
UnlockTreeControl();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Pop-up the menu for WinStations
|
||
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
||
|
((CWinAdminDoc*)GetDocument())->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
|
||
|
|
||
|
if(pNode) {
|
||
|
CMenu menu;
|
||
|
UINT nIDResource = 0;
|
||
|
|
||
|
switch(pNode->GetNodeType()) {
|
||
|
case NODE_ALL_SERVERS:
|
||
|
nIDResource = IDR_ALLSERVERS_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_DOMAIN:
|
||
|
nIDResource = IDR_DOMAIN_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_SERVER:
|
||
|
nIDResource = IDR_SERVER_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_WINSTATION:
|
||
|
nIDResource = IDR_WINSTATION_TREE_POPUP;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(nIDResource)
|
||
|
{
|
||
|
if(menu.LoadMenu(nIDResource))
|
||
|
{
|
||
|
CMenu *pMenu = menu.GetSubMenu(0);
|
||
|
|
||
|
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // end if(pNode)
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
} // end CAdminTreeView::OnContextMenu
|
||
|
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnRClick
|
||
|
//
|
||
|
// The Tree Common Control sends a WM_NOTIFY of NM_RCLICK when
|
||
|
// the user presses the right mouse button in the tree
|
||
|
//
|
||
|
void CAdminTreeView::OnRClick(NMHDR* pNMHDR, LRESULT* pResult)
|
||
|
{
|
||
|
CPoint ptScreen(::GetMessagePos());
|
||
|
|
||
|
LockTreeControl();
|
||
|
|
||
|
// Get a pointer to our document
|
||
|
CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
// TODO: Add your message handler code here
|
||
|
UINT flags;
|
||
|
HTREEITEM hItem;
|
||
|
CPoint ptClient = ptScreen;
|
||
|
ScreenToClient(&ptClient);
|
||
|
|
||
|
hItem = tree.HitTest(ptClient, &flags);
|
||
|
if((NULL == hItem) || !(TVHT_ONITEM & flags)) {
|
||
|
UnlockTreeControl();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Pop-up the menu
|
||
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
||
|
((CWinAdminDoc*)GetDocument())->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
|
||
|
|
||
|
if(pNode) {
|
||
|
CMenu menu;
|
||
|
UINT nIDResource = 0;
|
||
|
|
||
|
tree.SelectItem( hItem );
|
||
|
|
||
|
switch(pNode->GetNodeType()) {
|
||
|
case NODE_ALL_SERVERS:
|
||
|
nIDResource = IDR_ALLSERVERS_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_DOMAIN:
|
||
|
nIDResource = IDR_DOMAIN_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_SERVER:
|
||
|
nIDResource = IDR_SERVER_POPUP;
|
||
|
break;
|
||
|
|
||
|
case NODE_WINSTATION:
|
||
|
nIDResource = IDR_WINSTATION_TREE_POPUP;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(menu.LoadMenu( nIDResource ) )
|
||
|
{
|
||
|
CMenu *pMenu = menu.GetSubMenu(0);
|
||
|
|
||
|
if( pMenu != NULL )
|
||
|
{
|
||
|
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
} // end if(pNode)
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
} // end CAdminTreeView::OnRClick
|
||
|
|
||
|
|
||
|
|
||
|
//A false result means the server is disconnected
|
||
|
BOOL CAdminTreeView::ConnectToServer(CTreeCtrl* tree, HTREEITEM* hItem)
|
||
|
{
|
||
|
CTreeNode *pNode = (CTreeNode*)tree->GetItemData(*hItem);
|
||
|
|
||
|
if(pNode != NULL && *hItem == tree->GetSelectedItem() )
|
||
|
{
|
||
|
if( pNode->GetNodeType() == NODE_SERVER)
|
||
|
{
|
||
|
// Is this server in the "just disconnected" state
|
||
|
CServer *pServer = (CServer*)pNode->GetTreeObject();
|
||
|
// If both previous state and state are SS_NOT_CONNECTED,
|
||
|
// we know the user just disconnected from this server
|
||
|
if(pServer && pServer->IsState(SS_NOT_CONNECTED))
|
||
|
return false;
|
||
|
}
|
||
|
else if( pNode->GetNodeType( ) == NODE_DOMAIN )
|
||
|
{
|
||
|
CDomain *pDomain = ( CDomain * )pNode->GetTreeObject( );
|
||
|
|
||
|
if( pDomain != NULL && pDomain->GetThreadPointer() == NULL )
|
||
|
pDomain->StartEnumerating();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////
|
||
|
// F'N: CAdminTreeView::OnLButtonDown
|
||
|
//
|
||
|
void CAdminTreeView::OnLButtonDblClk(UINT nFlags, CPoint ptClient)
|
||
|
{
|
||
|
LockTreeControl();
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
UINT flags;
|
||
|
|
||
|
// Figure out what they clicked on
|
||
|
HTREEITEM hItem = tree.HitTest(ptClient, &flags);
|
||
|
if((NULL != hItem) && (TVHT_ONITEM & flags))
|
||
|
{
|
||
|
if (!ConnectToServer(&tree, &hItem))
|
||
|
{
|
||
|
LRESULT Result = 0xc0;
|
||
|
OnSelChange(NULL, &Result);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
|
||
|
CTreeView::OnLButtonDblClk(nFlags, ptClient);
|
||
|
}
|
||
|
|
||
|
|
||
|
LRESULT CAdminTreeView::OnAdminConnectToServer( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
OnEnterKey();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void CAdminTreeView::OnEnterKey( )
|
||
|
{
|
||
|
LockTreeControl();
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl();
|
||
|
|
||
|
// Figure out what's selected
|
||
|
HTREEITEM hItem = tree.GetSelectedItem( );
|
||
|
|
||
|
if (!ConnectToServer(&tree, &hItem))
|
||
|
{
|
||
|
LRESULT Result = 0xc0;
|
||
|
OnSelChange(NULL, &Result);
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl();
|
||
|
}
|
||
|
|
||
|
void CAdminTreeView::OnSetFocus( CWnd *pOld )
|
||
|
{
|
||
|
CWnd::OnSetFocus( pOld );
|
||
|
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument();
|
||
|
|
||
|
pDoc->RegisterLastFocus( TREE_VIEW );
|
||
|
|
||
|
}
|
||
|
|
||
|
//=---------------------------------------------------------------------------------------
|
||
|
// wp is the node type to expand on
|
||
|
// this computer
|
||
|
// favorite item
|
||
|
// domain item
|
||
|
|
||
|
LRESULT CAdminTreeView::OnAdminGotoServer( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
// todo use wp correctly
|
||
|
|
||
|
CServer *pServer = ( CServer * )lp;
|
||
|
|
||
|
if( pServer == NULL )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnAdminGotoServer invalid server arg\n" );
|
||
|
return 0 ;
|
||
|
}
|
||
|
|
||
|
LockTreeControl( );
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl( );
|
||
|
|
||
|
HTREEITEM hTreeItem = pServer->GetTreeItem( );
|
||
|
|
||
|
if( hTreeItem != NULL )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView!OnAdminGotoServer - Server treeitem was found\n" );
|
||
|
|
||
|
tree.SelectItem(hTreeItem);
|
||
|
|
||
|
tree.Expand(hTreeItem, TVE_EXPAND);
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//=---------------------------------------------------------------------------------------
|
||
|
// wp and lp not used
|
||
|
//
|
||
|
LRESULT CAdminTreeView::OnAdminDelFavServer( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
// get the current treenode
|
||
|
// determine if its a fav folder or if its parent a fav folder
|
||
|
// if so get the server and kill it
|
||
|
LockTreeControl( );
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl( );
|
||
|
|
||
|
HTREEITEM hTreeItem = tree.GetSelectedItem();
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( hTreeItem == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
HTREEITEM hTreeRoot = tree.GetRootItem( );
|
||
|
|
||
|
if( hTreeRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// get fav folder
|
||
|
|
||
|
HTREEITEM hTreeFavRoot = tree.GetNextItem( hTreeRoot , TVGN_NEXT );
|
||
|
|
||
|
if( hTreeFavRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( hTreeFavRoot == hTreeItem )
|
||
|
{
|
||
|
// not a cool thing here ignore
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hTreeRoot = tree.GetNextItem( hTreeItem , TVGN_PARENT );
|
||
|
|
||
|
if( hTreeFavRoot == hTreeRoot )
|
||
|
{
|
||
|
// yes we're talking about a fav node that the user wants to delete
|
||
|
|
||
|
CTreeNode *pNode = ( CTreeNode* )tree.GetItemData( hTreeItem );
|
||
|
|
||
|
if( pNode != NULL && pNode->GetNodeType() == NODE_SERVER )
|
||
|
{
|
||
|
CServer *pServer = ( CServer* )pNode->GetTreeObject();
|
||
|
|
||
|
// sanity check
|
||
|
if( pServer != NULL && pServer->GetTreeItemFromFav() == hTreeItem )
|
||
|
{
|
||
|
OnAdminRemoveServerFromFavs( 0 , ( LPARAM )pServer );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}while( 0 );
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
LRESULT CAdminTreeView::OnGetTVStates( WPARAM , LPARAM )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnGetTVStates\n" );
|
||
|
|
||
|
DWORD dwStates = 0;
|
||
|
|
||
|
// find out the tri-states
|
||
|
HTREEITEM hRoot;
|
||
|
|
||
|
LockTreeControl( );
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl( );
|
||
|
|
||
|
|
||
|
hRoot = tree.GetRootItem( ); // this computer
|
||
|
|
||
|
if( hRoot != NULL )
|
||
|
{
|
||
|
if( tree.GetItemState( hRoot , TVIS_EXPANDED ) & TVIS_EXPANDED )
|
||
|
{
|
||
|
dwStates = TV_THISCOMP;
|
||
|
}
|
||
|
|
||
|
hRoot = tree.GetNextItem( hRoot , TVGN_NEXT ); // favorites
|
||
|
|
||
|
if( hRoot != NULL && tree.GetItemState( hRoot , TVIS_EXPANDED ) & TVIS_EXPANDED )
|
||
|
{
|
||
|
dwStates |= TV_FAVS;
|
||
|
}
|
||
|
|
||
|
hRoot = tree.GetNextItem( hRoot , TVGN_NEXT ); // all servers
|
||
|
|
||
|
if( hRoot != NULL && tree.GetItemState( hRoot , TVIS_EXPANDED ) & TVIS_EXPANDED )
|
||
|
{
|
||
|
dwStates |= TV_ALLSERVERS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return ( LRESULT )dwStates;
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
LRESULT CAdminTreeView::OnUpdateTVState( WPARAM , LPARAM )
|
||
|
{
|
||
|
LRESULT lResult = 0xc0;
|
||
|
HTREEITEM hThisComputerRootItem = GetTreeCtrl().GetRootItem( );
|
||
|
HTREEITEM hFavRoot = GetTreeCtrl().GetNextItem( hThisComputerRootItem , TVGN_NEXT );
|
||
|
HTREEITEM hRoot = GetTreeCtrl().GetNextItem( hFavRoot , TVGN_NEXT );
|
||
|
// We want to default to having the current server being the
|
||
|
// currently selected item in the tree and be expanded
|
||
|
|
||
|
if( hThisComputerRootItem != NULL && ( g_dwTreeViewExpandedStates & TV_THISCOMP ) )
|
||
|
{
|
||
|
HTREEITEM hThisComputer = GetTreeCtrl().GetNextItem( hThisComputerRootItem , TVGN_CHILD );
|
||
|
|
||
|
if( hThisComputer != NULL )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem(hThisComputer);
|
||
|
GetTreeCtrl().Expand(hThisComputer, TVE_EXPAND);
|
||
|
// GetTreeCtrl().Expand(hDomain, TVE_EXPAND);
|
||
|
//lResult = 0xc0;
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( hFavRoot != NULL && ( g_dwTreeViewExpandedStates & TV_FAVS ) )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem( hFavRoot );
|
||
|
GetTreeCtrl().Expand( hFavRoot , TVE_EXPAND );
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
|
||
|
if( hRoot != NULL && ( g_dwTreeViewExpandedStates & TV_ALLSERVERS ) )
|
||
|
{
|
||
|
GetTreeCtrl().SelectItem( hRoot );
|
||
|
GetTreeCtrl().Expand( hRoot , TVE_EXPAND );
|
||
|
OnSelChange( NULL , &lResult );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
void CAdminTreeView::OnBeginDrag( NMHDR *pNMHDR , LRESULT *pResult )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnBeginDrag\n" );
|
||
|
|
||
|
RECT rc;
|
||
|
|
||
|
NMTREEVIEW *pTV = ( NMTREEVIEW * )pNMHDR;
|
||
|
|
||
|
if( pTV != NULL )
|
||
|
{
|
||
|
|
||
|
if( m_pimgDragList != NULL )
|
||
|
{
|
||
|
// this should never happen
|
||
|
ODS( L"There is a possible leak CAdminTreeView!OnBeginDrag\n" );
|
||
|
|
||
|
delete m_pimgDragList;
|
||
|
|
||
|
m_pimgDragList = NULL;
|
||
|
}
|
||
|
|
||
|
if( pTV->itemNew.hItem != NULL )
|
||
|
{
|
||
|
m_pimgDragList = GetTreeCtrl().CreateDragImage( pTV->itemNew.hItem );
|
||
|
}
|
||
|
|
||
|
if( m_pimgDragList != NULL )
|
||
|
{
|
||
|
GetTreeCtrl().GetItemRect( pTV->itemNew.hItem , &rc , FALSE );
|
||
|
|
||
|
CPoint cp( pTV->ptDrag.x - rc.left , pTV->ptDrag.y - rc.top );
|
||
|
|
||
|
/*
|
||
|
HCURSOR hCursor = ::LoadCursor( NULL, IDC_CROSS );
|
||
|
|
||
|
ICONINFO iconinfo;
|
||
|
|
||
|
::GetIconInfo( ( HICON )hCursor , &iconinfo );
|
||
|
*/
|
||
|
|
||
|
|
||
|
m_pimgDragList->BeginDrag( 0 , CPoint( 0 , 0 ) );
|
||
|
|
||
|
/*
|
||
|
cp.x -= iconinfo.xHotspot;
|
||
|
cp.y -= iconinfo.yHotspot;
|
||
|
|
||
|
m_pimgDragList->SetDragCursorImage( 0 , cp );
|
||
|
*/
|
||
|
|
||
|
m_pimgDragList->DragEnter( &GetTreeCtrl( ) , cp );
|
||
|
|
||
|
SetCapture();
|
||
|
|
||
|
// this is for us to check when we're not in the client area
|
||
|
m_nTimer = SetTimer( 1 , 50 , NULL );
|
||
|
|
||
|
//ShowCursor( FALSE );
|
||
|
|
||
|
m_hDragItem = pTV->itemNew.hItem;
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pResult = 0;
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
void CAdminTreeView::OnTimer( UINT nIDEvent )
|
||
|
{
|
||
|
UINT uflags;
|
||
|
|
||
|
POINT pt;
|
||
|
|
||
|
CTreeCtrl &cTree = GetTreeCtrl( );
|
||
|
|
||
|
GetCursorPos(&pt);
|
||
|
|
||
|
cTree.ScreenToClient( &pt );
|
||
|
|
||
|
if( m_nTimer == 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
HTREEITEM hItem;
|
||
|
|
||
|
HTREEITEM hTreeItem = cTree.HitTest( CPoint( pt.x , pt.y ) , &uflags );
|
||
|
|
||
|
if( uflags & TVHT_ABOVE )
|
||
|
{
|
||
|
ODS( L"scrolling up...\n" );
|
||
|
|
||
|
hItem = cTree.GetFirstVisibleItem( );
|
||
|
|
||
|
hItem = cTree.GetNextItem( hItem , TVGN_PREVIOUSVISIBLE );
|
||
|
|
||
|
if( hItem != NULL )
|
||
|
{
|
||
|
cTree.Invalidate( );
|
||
|
|
||
|
cTree.EnsureVisible( hItem );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if( uflags & TVHT_BELOW )
|
||
|
{
|
||
|
ODS( L"scrolling down...\n" );
|
||
|
|
||
|
hItem = cTree.GetFirstVisibleItem( );
|
||
|
|
||
|
hItem = cTree.GetNextItem( hItem , TVGN_NEXT );
|
||
|
|
||
|
if( hItem != NULL )
|
||
|
{
|
||
|
cTree.EnsureVisible( hItem );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
void CAdminTreeView::OnLButtonUp( UINT uFlags , CPoint cp )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnLButtonUp\n" );
|
||
|
|
||
|
if( m_hDragItem != NULL && m_pimgDragList != NULL )
|
||
|
{
|
||
|
m_pimgDragList->DragLeave( &GetTreeCtrl( ) );
|
||
|
|
||
|
m_pimgDragList->EndDrag( );
|
||
|
|
||
|
m_pimgDragList->DeleteImageList( );
|
||
|
|
||
|
delete m_pimgDragList;
|
||
|
|
||
|
m_pimgDragList = NULL;
|
||
|
|
||
|
KillTimer( m_nTimer );
|
||
|
|
||
|
m_nTimer = 0;
|
||
|
|
||
|
ReleaseCapture( );
|
||
|
|
||
|
Invalidate( );
|
||
|
|
||
|
// ShowCursor( TRUE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
void CAdminTreeView::OnMouseMove( UINT uFlags , CPoint cp )
|
||
|
{
|
||
|
if( m_pimgDragList != NULL )
|
||
|
{
|
||
|
UINT uflags;
|
||
|
|
||
|
HTREEITEM hTreeItem = GetTreeCtrl( ).HitTest( cp , &uflags );
|
||
|
|
||
|
if( hTreeItem != GetTreeCtrl( ).GetDropHilightItem( ) )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView::OnMouseMove NOT!!\n");
|
||
|
m_pimgDragList->DragLeave( &GetTreeCtrl( ) );
|
||
|
|
||
|
GetTreeCtrl( ).SelectDropTarget( NULL );
|
||
|
GetTreeCtrl( ).SelectDropTarget( hTreeItem );
|
||
|
|
||
|
m_pimgDragList->DragEnter( &GetTreeCtrl( ) , cp );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pimgDragList->DragMove( cp );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//=-------------------------------------------------------------
|
||
|
LRESULT CAdminTreeView::OnEmptyFavorites( WPARAM wp, LPARAM )
|
||
|
{
|
||
|
ODS( L"CAdminTreeView!OnEmptyFavorites\n" );
|
||
|
|
||
|
// check to see if there are any items in the view
|
||
|
|
||
|
LockTreeControl( );
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl( );
|
||
|
|
||
|
int nRet;
|
||
|
|
||
|
HTREEITEM hTreeRoot = tree.GetRootItem( );
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( hTreeRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// get fav folder
|
||
|
|
||
|
HTREEITEM hTreeFavRoot = tree.GetNextItem( hTreeRoot , TVGN_NEXT );
|
||
|
|
||
|
if( hTreeFavRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
HTREEITEM hItem = tree.GetNextItem( hTreeFavRoot , TVGN_CHILD );
|
||
|
|
||
|
if( hItem == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// warn the user about losing the entire favorite list
|
||
|
|
||
|
CString cstrMsg;
|
||
|
CString cstrTitle;
|
||
|
|
||
|
cstrMsg.LoadString( IDS_EMPTYFOLDER );
|
||
|
cstrTitle.LoadString( AFX_IDS_APP_TITLE );
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef _STRESS_BUILD
|
||
|
if( ( BOOL )wp != TRUE )
|
||
|
{
|
||
|
#endif
|
||
|
|
||
|
|
||
|
nRet = MessageBox( cstrMsg ,
|
||
|
cstrTitle ,
|
||
|
MB_YESNO | MB_ICONINFORMATION );
|
||
|
|
||
|
#ifdef _STRESS_BUILD
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nRet = IDYES;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
if( nRet == IDYES )
|
||
|
{
|
||
|
// loop through every item and remove the item
|
||
|
HTREEITEM hNextItem = hItem;
|
||
|
|
||
|
while( hItem != NULL )
|
||
|
{
|
||
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
||
|
|
||
|
hNextItem = tree.GetNextItem( hItem , TVGN_NEXT );
|
||
|
|
||
|
if( pNode != NULL )
|
||
|
{
|
||
|
// Is it the same item as is selected
|
||
|
if( pNode->GetNodeType() == NODE_SERVER )
|
||
|
{
|
||
|
CServer *pServer = (CServer*)pNode->GetTreeObject();
|
||
|
|
||
|
// skip this server if its being disconnected
|
||
|
|
||
|
if( !pServer->IsState( SS_DISCONNECTING ) )
|
||
|
{
|
||
|
SendMessage( WM_ADMIN_REMOVESERVERFROMFAV , 0 , ( LPARAM )pServer );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hItem = hNextItem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}while( 0 );
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//=----------------------------------------------------------------
|
||
|
LRESULT CAdminTreeView::OnIsFavListEmpty( WPARAM wp , LPARAM lp )
|
||
|
{
|
||
|
LockTreeControl( );
|
||
|
|
||
|
CTreeCtrl &tree = GetTreeCtrl( );
|
||
|
|
||
|
HTREEITEM hTreeRoot = tree.GetRootItem( );
|
||
|
|
||
|
BOOL bEmpty = TRUE;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( hTreeRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// get fav folder
|
||
|
|
||
|
HTREEITEM hTreeFavRoot = tree.GetNextItem( hTreeRoot , TVGN_NEXT );
|
||
|
|
||
|
if( hTreeFavRoot == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
HTREEITEM hItem = tree.GetNextItem( hTreeFavRoot , TVGN_CHILD );
|
||
|
|
||
|
if( hItem == NULL )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bEmpty = FALSE;
|
||
|
|
||
|
} while( 0 );
|
||
|
|
||
|
UnlockTreeControl( );
|
||
|
|
||
|
return ( LRESULT )bEmpty;
|
||
|
}
|
||
|
|
||
|
|