mirror of https://github.com/tongzx/nt5src
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
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
|
|
|
|
|