Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

453 lines
12 KiB

/*******************************************************************************
*
* basetree.cpp
*
* implementation of the CBaseTreeView 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\basetree.cpp $
*
* Rev 1.4 19 Feb 1998 17:39:58 donm
* removed latest extension DLL support
*
* Rev 1.2 19 Jan 1998 17:03:10 donm
* new ui behavior for domains and servers
*
* Rev 1.1 03 Nov 1997 15:21:28 donm
* update
*
* Rev 1.0 13 Oct 1997 22:31:30 donm
* Initial revision.
*
*******************************************************************************/
#include "stdafx.h"
#include "winadmin.h"
#include "admindoc.h"
#include "basetree.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////
// MESSAGE MAP: CBaseTreeView
//
IMPLEMENT_DYNCREATE(CBaseTreeView, CTreeView)
BEGIN_MESSAGE_MAP(CBaseTreeView, CTreeView)
//{{AFX_MSG_MAP(CBaseTreeView)
ON_MESSAGE(WM_ADMIN_EXPANDALL, OnExpandAll)
ON_MESSAGE(WM_ADMIN_COLLAPSEALL, OnCollapseAll)
ON_MESSAGE(WM_ADMIN_COLLAPSETOSERVERS, OnCollapseToThirdLevel)
ON_MESSAGE(WM_ADMIN_COLLAPSETODOMAINS, OnCollapseToRootChildren)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChange)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////////////
// F'N: CBaseTreeView ctor
//
CBaseTreeView::CBaseTreeView()
{
m_bInitialExpand = FALSE;
} // end CBaseTreeView ctor
//////////////////////////
// F'N: CBaseTreeView dtor
//
CBaseTreeView::~CBaseTreeView()
{
} // end CBaseTreeView dtor
/////////////////////////////
// F'N: CBaseTreeView::OnDraw
//
void CBaseTreeView::OnDraw(CDC* pDC)
{
CWinAdminDoc* pDoc = (CWinAdminDoc*)GetDocument();
ASSERT(pDoc != NULL);
ASSERT_VALID(pDoc);
} // end CBaseTreeView::OnDraw
#ifdef _DEBUG
//////////////////////////////////
// F'N: CBaseTreeView::AssertValid
//
void CBaseTreeView::AssertValid() const
{
CTreeView::AssertValid();
} // end CBaseTreeView::AssertValid
///////////////////////////
// F'N: CBaseTreeView::Dump
//
void CBaseTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
} // end CBaseTreeView::Dump
#endif
//////////////////////////////////////
// F'N: CBaseTreeView::PreCreateWindow
//
BOOL CBaseTreeView::PreCreateWindow(CREATESTRUCT& cs)
{
// Set the style bits for the CTreeCtrl
cs.style |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP
| TVS_SHOWSELALWAYS;
return CTreeView::PreCreateWindow(cs);
} // end CBaseTreeView::PreCreateWindow
/////////////////////////////////////
// F'N: CBaseTreeView::BuildImageList
//
void CBaseTreeView::BuildImageList()
{
// do nothing
} // end CBaseTreeView::BuildImageList
//////////////////////////////////////
// F'N: CBaseTreeView::OnInitialUpdate
//
// - constructs the image list for the tree, saving indices to each icon
// in member variables (m_idxCitrix, m_idxServer, etc.)
//
void CBaseTreeView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
// build the image list for the tree control
BuildImageList();
} // end CBaseTreeView::OnInitialUpdate
/////////////////////////////////////////
// F'N: CBaseTreeView::AddIconToImageList
//
// - loads the appropriate icon, adds it to m_ImageList, and returns
// the newly-added icon's index in the image list
//
int CBaseTreeView::AddIconToImageList(int iconID)
{
HICON hIcon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(iconID));
return m_ImageList.Add(hIcon);
} // end CBaseTreeView::AddIconToImageList
////////////////////////////////////
// F'N: CBaseTreeView::AddItemToTree
//
// Adds an item with the given attributes to the CTreeCtrl
//
HTREEITEM CBaseTreeView::AddItemToTree(HTREEITEM hParent, CString szText, HTREEITEM hInsAfter, int iImage, LPARAM lParam)
{
HTREEITEM hItem;
TV_ITEM tvItem = {0};
TV_INSERTSTRUCT tvInsert;
ASSERT(lParam);
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
TCHAR temp[255];
wcscpy(temp, szText);
tvItem.pszText = temp;
tvItem.cchTextMax = lstrlen(szText);
tvItem.iImage = iImage;
tvItem.iSelectedImage = iImage;
tvItem.lParam = lParam;
tvInsert.item = tvItem;
tvInsert.hInsertAfter = hInsAfter;
tvInsert.hParent = hParent;
hItem = GetTreeCtrl().InsertItem(&tvInsert);
if(!m_bInitialExpand && hItem) {
m_bInitialExpand = GetTreeCtrl().Expand(GetTreeCtrl().GetRootItem(), TVE_EXPAND);
}
return hItem;
} // end CBaseTreeView::AddItemToTree
///////////////////////////////////
// F'N: CBaseTreeView::GetCurrentNode
//
DWORD_PTR CBaseTreeView::GetCurrentNode()
{
LockTreeControl();
HTREEITEM hCurr = GetTreeCtrl().GetSelectedItem();
DWORD_PTR node = GetTreeCtrl().GetItemData(hCurr);
UnlockTreeControl();
return node;
} // end CBaseTreeView::GetCurrentNode
///////////////////////////////////
// F'N: CBaseTreeView::OnSelChange
//
// - this f'n posts a WM_ADMIN_CHANGEVIEW message to the mainframe, passing along
// a pointer to the newly selected tree item's info structure in lParam so
// that the mainframe can make an intelligent decision as far as how to
// interpret the message
//
// Passes TRUE as wParam for WM_ADMIN_CHANGEVIEW message to signify
// that the message was caused by a user mouse click
//
void CBaseTreeView::OnSelChange(NMHDR* pNMHDR, LRESULT* pResult)
{
LockTreeControl();
HTREEITEM hCurr = GetTreeCtrl().GetSelectedItem();
DWORD_PTR value = GetTreeCtrl().GetItemData(hCurr);
UnlockTreeControl();
// Tell the document that the current item in the tree has changed
CTreeNode *pNode = (CTreeNode*)value;
if( pNode != NULL )
{
((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING);
((CWinAdminDoc*)GetDocument())->SetTreeCurrent( pNode->GetTreeObject(), pNode->GetNodeType());
// send a "change view" msg to the mainframe with the info structure ptr as a parm
CFrameWnd* pMainWnd = (CFrameWnd*)AfxGetMainWnd();
pMainWnd->PostMessage(WM_ADMIN_CHANGEVIEW, *pResult == 0xc0 ? TRUE : FALSE , (LPARAM)pNode); // SendMessage causes blank pages
}
*pResult = 0;
} // end CBaseTreeView::OnSelChange
///////////////////////////////////
// F'N: CBaseTreeView::ForceSelChange
//
// Called by treeview when the state of an item in the tree has changed
// which is likely to cause the current view in the right pane to change.
//
// This f'n posts a WM_ADMIN_CHANGEVIEW message to the mainframe, passing along
// a pointer to the newly selected tree item's info structure in lParam so
// that the mainframe can make an intelligent decision as far as how to
// interpret the message
//
// Puts a FALSE in wParam of the WM_ADMIN_CHANGEVIEW message which
// tells the right pane that this was not caused by a user clicking
// on the item in the tree
//
void CBaseTreeView::ForceSelChange()
{
LockTreeControl();
HTREEITEM hCurr = GetTreeCtrl().GetSelectedItem();
DWORD_PTR value = GetTreeCtrl().GetItemData(hCurr);
UnlockTreeControl();
// Tell the document that the current item in the tree has changed
((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING);
((CWinAdminDoc*)GetDocument())->SetTreeCurrent(((CTreeNode*)value)->GetTreeObject(), ((CTreeNode*)value)->GetNodeType());
// send a "change view" msg to the mainframe with the info structure ptr as a parm
CFrameWnd* pMainWnd = (CFrameWnd*)AfxGetMainWnd();
pMainWnd->PostMessage(WM_ADMIN_CHANGEVIEW, FALSE, (LPARAM)value); // SendMessage causes blank pages
} // end CBaseTreeView::ForceSelChange
////////////////////////////////
// F'N: CBaseTreeView::OnExpandAll
//
// Expands all levels of the tree, starting at the root
//
LRESULT CBaseTreeView::OnExpandAll(WPARAM wParam, LPARAM lParam)
{
LockTreeControl();
// get a count of the items in the tree
UINT itemCount = GetTreeCtrl().GetCount();
// get the handle of the root item and Expand it
HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
for(UINT i = 0; i < itemCount; i++) {
GetTreeCtrl().Expand(hTreeItem, TVE_EXPAND);
hTreeItem = GetTreeCtrl().GetNextItem(hTreeItem, TVGN_NEXTVISIBLE);
}
UnlockTreeControl();
return 0;
} // end CBaseTreeView::OnExpandAll
////////////////////////////////
// F'N: CBaseTreeView::Collapse
//
// Helper function to collapse a tree item
// NOTE: This function calls itself recursively
//
void CBaseTreeView::Collapse(HTREEITEM hItem)
{
LockTreeControl();
CTreeCtrl &tree = GetTreeCtrl();
// Get his first child and collapse him
HTREEITEM hChild = tree.GetNextItem(hItem, TVGN_CHILD);
if(hChild) Collapse(hChild);
// Collapse him
tree.Expand(hItem, TVE_COLLAPSE);
// Get his first sibling and collapse him
HTREEITEM hSibling = tree.GetNextItem(hItem, TVGN_NEXT);
if(hSibling) Collapse(hSibling);
UnlockTreeControl();
} // end CBaseTreeView::Collapse
////////////////////////////////
// F'N: CBaseTreeView::OnCollapseAll
//
// Collapses all levels of the tree, starting at the root
//
LRESULT CBaseTreeView::OnCollapseAll(WPARAM wParam, LPARAM lParam)
{
// Call the recursive function to do all
// the collapsing
Collapse(GetTreeCtrl().GetRootItem());
return 0;
} // end CBaseTreeView::OnCollapseAll
////////////////////////////////
// F'N: CBaseTreeView::OnCollapseToThirdLevel
//
// Collapses tree down to show just root children and their children
//
LRESULT CBaseTreeView::OnCollapseToThirdLevel(WPARAM wParam, LPARAM lParam)
{
LockTreeControl();
// Get the root item
HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
// Get the first node
HTREEITEM hRootChild = GetTreeCtrl().GetNextItem(hTreeItem, TVGN_CHILD);
while(hRootChild) {
HTREEITEM hThirdLevel = GetTreeCtrl().GetNextItem(hRootChild, TVGN_CHILD);
while(hThirdLevel) {
// collapse him
GetTreeCtrl().Expand(hThirdLevel, TVE_COLLAPSE);
// go to the next one
hThirdLevel = GetTreeCtrl().GetNextItem(hThirdLevel, TVGN_NEXT);
}
hRootChild = GetTreeCtrl().GetNextItem(hRootChild, TVGN_NEXT);
}
UnlockTreeControl();
return 0;
} // end CBaseTreeView::OnCollapseToThirdLevel
////////////////////////////////
// F'N: CBaseTreeView::OnCollapseToRootChildren
//
// Collapses tree down to show just root and it's immediate children
//
LRESULT CBaseTreeView::OnCollapseToRootChildren(WPARAM wParam, LPARAM lParam)
{
LockTreeControl();
// Get the root item
HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
// Get the first node
HTREEITEM hNode = GetTreeCtrl().GetNextItem(hTreeItem, TVGN_CHILD);
while(hNode) {
Collapse(hNode);
// go to the next node
hNode = GetTreeCtrl().GetNextItem(hNode, TVGN_NEXT);
}
UnlockTreeControl();
return 0;
} // end CBaseTreeView::OnCollapseToRootChildren
////////////////////////////////
// F'N: CBaseTreeView::OnDestroy
//
void CBaseTreeView::OnDestroy()
{
LockTreeControl();
UINT itemCount = GetTreeCtrl().GetCount();
HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
for(UINT i = 0; i < itemCount; i++) {
CTreeNode *node = ((CTreeNode*)GetTreeCtrl().GetItemData(hTreeItem));
delete (CTreeNode*)(GetTreeCtrl().GetItemData(hTreeItem));
hTreeItem = GetNextItem(hTreeItem);
}
UnlockTreeControl();
} // end CBaseTreeView::OnDestroy
////////////////////////////////
// F'N: CBaseTreeView::GetNextItem
//
// GetNextItem - Get next item as if outline was completely expanded
// Returns - The item immediately below the reference item
// hItem - The reference item
//
HTREEITEM CBaseTreeView::GetNextItem( HTREEITEM hItem )
{
HTREEITEM hti;
CTreeCtrl &tree = GetTreeCtrl();
if(tree.ItemHasChildren( hItem ) )
return tree.GetChildItem( hItem ); // return first child
else { // return next sibling item
// Go up the tree to find a parent's sibling if needed.
while( (hti = tree.GetNextSiblingItem( hItem )) == NULL ) {
if( (hItem = tree.GetParentItem( hItem ) ) == NULL )
return NULL;
}
}
return hti;
} // end CBaseTreeView::GetNextItem