/******************************************************************************* * * apptree.cpp * * implementation of the CAppTreeView 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\apptree.cpp $ * * Rev 1.2 16 Feb 1998 16:00:06 donm * modifications to support pICAsso extension * * Rev 1.1 03 Nov 1997 15:21:24 donm * update * * Rev 1.0 13 Oct 1997 22:31:20 donm * Initial revision. * *******************************************************************************/ #include "stdafx.h" #include "winadmin.h" #include "admindoc.h" #include "apptree.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////// // MESSAGE MAP: CAppTreeView // IMPLEMENT_DYNCREATE(CAppTreeView, CBaseTreeView) BEGIN_MESSAGE_MAP(CAppTreeView, CBaseTreeView) //{{AFX_MSG_MAP(CAppTreeView) ON_MESSAGE(WM_EXT_ADD_APPLICATION, OnExtAddApplication) ON_MESSAGE(WM_EXT_REMOVE_APPLICATION, OnExtRemoveApplication) ON_MESSAGE(WM_EXT_APP_CHANGED, OnExtAppChanged) ON_MESSAGE(WM_EXT_ADD_APP_SERVER, OnExtAddAppServer) ON_MESSAGE(WM_EXT_REMOVE_APP_SERVER, OnExtRemoveAppServer) ON_MESSAGE(WM_ADMIN_VIEWS_READY, OnAdminViewsReady) ON_MESSAGE(WM_ADMIN_UPDATE_SERVER, OnAdminUpdateServer) ON_MESSAGE(WM_ADMIN_ADD_WINSTATION, OnAdminAddWinStation) ON_MESSAGE(WM_ADMIN_REMOVE_WINSTATION, OnAdminRemoveWinStation) ON_MESSAGE(WM_ADMIN_UPDATE_WINSTATION, OnAdminUpdateWinStation) ON_WM_CONTEXTMENU() ON_NOTIFY(NM_RCLICK, AFX_IDW_PANE_FIRST, OnRClick) ON_NOTIFY(NM_RCLICK, 1, OnRClick) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ////////////////////////// // CAppTreeView ctor // CAppTreeView::CAppTreeView() { } // end CAppTreeView ctor ////////////////////////// // CAppTreeView dtor // CAppTreeView::~CAppTreeView() { } // end CAppTreeView dtor #ifdef _DEBUG ////////////////////////////////// // CAppTreeView::AssertValid // void CAppTreeView::AssertValid() const { CBaseTreeView::AssertValid(); } // end CAppTreeView::AssertValid /////////////////////////// // CAppTreeView::Dump // void CAppTreeView::Dump(CDumpContext& dc) const { CBaseTreeView::Dump(dc); } // end CAppTreeView::Dump #endif ///////////////////////////////////// // CAppTreeView::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 CAppTreeView::BuildImageList() { m_ImageList.Create(16, 16, TRUE, 7, 0); m_idxApps = AddIconToImageList(IDI_APPS); m_idxGenericApp = AddIconToImageList(IDI_GENERIC_APP); m_idxServer = AddIconToImageList(IDI_SERVER); m_idxNotSign = AddIconToImageList(IDI_NOTSIGN); m_idxQuestion = AddIconToImageList(IDI_QUESTIONMARK); m_idxUser = AddIconToImageList(IDI_USER); m_idxCurrentServer = AddIconToImageList(IDI_CURRENT_SERVER); m_idxCurrentUser = AddIconToImageList(IDI_CURRENT_USER); 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 CAppTreeView::BuildImageList ////////////////////////////////// // CAppTreeView::OnAdminViewsReady // LRESULT CAppTreeView::OnAdminViewsReady(WPARAM wParam, LPARAM lParam) { LockTreeControl(); // Get a pointer to our document CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument(); // add the root to the tree CString citrix; citrix.LoadString(IDS_PUBLISHED_APPS); CTreeNode* pRootNode = new CTreeNode(NODE_PUBLISHED_APPS, NULL); if(pRootNode) { HTREEITEM hRoot = AddItemToTree(NULL, citrix, TVI_ROOT, m_idxApps, (DWORD)pRootNode); if(!hRoot) delete pRootNode; } UnlockTreeControl(); return 0; } // end CAppTreeView::OnAdminViewsReady //////////////////////////////// // CAppTreeView::OnExtAddApplication // // Message Handler to add a published application to the tree // Pointer to ExtAddTreeNode is in wParam // Pointer to CPublishedApp is in lParam // LRESULT CAppTreeView::OnExtAddApplication(WPARAM wParam, LPARAM lParam) { LockTreeControl(); ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam; // First make sure the application isn't already in the tree HTREEITEM hRoot = GetTreeCtrl().GetRootItem(); // Get the first application HTREEITEM hItem = GetTreeCtrl().GetNextItem(hRoot, TVGN_CHILD); while(hItem) { // Get the data attached to the tree item CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hItem); // Is this the application we want to add? if((CObject*)node->GetTreeObject() == pExtAddTreeNode->pObject) return 0; hItem = GetTreeCtrl().GetNextItem(hItem, TVGN_NEXT); } // Add the published application to the tree // Create a CTreeNode object with info about this tree node CTreeNode* pNode = new CTreeNode(NODE_APPLICATION, pExtAddTreeNode->pObject); if(pNode) { HTREEITEM hApplication = AddItemToTree(hRoot, pExtAddTreeNode->Name, TVI_SORT, m_idxGenericApp, (DWORD)pNode); if(!hApplication) delete pNode; if(!((CPublishedApp*)pExtAddTreeNode->pObject)->IsState(PAS_GOOD)) GetTreeCtrl().SetItemState(hApplication, STATE_QUESTION, 0x0F00); ((CPublishedApp*)pExtAddTreeNode->pObject)->SetTreeItem(hApplication); } UnlockTreeControl(); return 0; } // end CAppTreeView::OnExtAddApplication //////////////////////////////// // CAppTreeView::OnExtRemoveApplication // // Message Handler to remove a published application from the tree // Pointer to CPublishedApp is in lParam // LRESULT CAppTreeView::OnExtRemoveApplication(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); CPublishedApp *pApplication = (CPublishedApp*)lParam; HTREEITEM hApplication = pApplication->GetTreeItem(); if(!hApplication) return 0; LockTreeControl(); // Get the data attached to this tree node CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication); if(node) { // Is this the application we want to remove CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject(); // Make sure the tree node is correct if(pTreeApp != pApplication) { UnlockTreeControl(); return 0; } } else { UnlockTreeControl(); return 0; } // Loop through it's children and delete their data HTREEITEM hAppServer = GetTreeCtrl().GetNextItem(hApplication, TVGN_CHILD); while(hAppServer) { CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hAppServer); if(pTreeNode) { delete pTreeNode; } // Loop through the users nodes under the AppServer in the tree HTREEITEM hUser = GetTreeCtrl().GetNextItem(hAppServer, TVGN_CHILD); while(hUser) { CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hUser); if(pTreeNode) { CWinStation *pWinStation = (CWinStation*)pTreeNode->GetTreeObject(); if(pWinStation) pWinStation->SetAppTreeItem(NULL); delete pTreeNode; } } hAppServer = GetTreeCtrl().GetNextItem(hAppServer, TVGN_NEXT); } // Delete the data attached to the tree item delete node; // Let the application know he is no longer in the tree pApplication->SetTreeItem(NULL); // Remove the application from the tree // This SHOULD remove all it's children GetTreeCtrl().DeleteItem(hApplication); UnlockTreeControl(); return 0; } // end CAppTreeView::OnExtRemoveApplication ///////////////////////////////////////// // CAppTreeView::OnExtAppChanged // LRESULT CAppTreeView::OnExtAppChanged(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); // we only care if it is a state change if(wParam & ACF_STATE) { CPublishedApp *pApplication = (CPublishedApp*)lParam; HTREEITEM hApplication = pApplication->GetTreeItem(); if(!hApplication) return 0; LockTreeControl(); // Get the data attached to this tree node CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication); if(node) { // Is this the app we want to update? CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject(); // Make sure the tree node is correct if(pTreeApp != pApplication) { UnlockTreeControl(); return 0; } } else { UnlockTreeControl(); return 0; } USHORT NewState; // Remember the previous state USHORT PreviousState = GetTreeCtrl().GetItemState(hApplication, 0x0F00); // Change the icon/overlay for the app // If we aren't done getting all the information about this app, // put a question mark over the icon if(pApplication->IsState(PAS_GETTING_INFORMATION)) 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(hApplication, NewState, 0x0F00); } return 0; } // end CAppTreeView::OnExtAppChanged ///////////////////////////////////////// // CAppTreeView::DetermineServerIcon // // determines which icon to display for a Server // in the tree // int CAppTreeView::DetermineServerIcon(CServer *pServer) { if(!pServer) return m_idxServerNotConnected; 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 CAooTreeView::DetermineServerIcon //////////////////////////////// // CAppTreeView::OnExtAddAppServer // // Message Handler to add a server beneath a published application // Pointer to ExtAddTreeNode is in wParam // Pointer to CAppServer is in lParam // LRESULT CAppTreeView::OnExtAddAppServer(WPARAM wParam, LPARAM lParam) { ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam; HTREEITEM hParent = pExtAddTreeNode->hParent; if(!hParent) return 0; CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument(); CServer *pServer = pDoc->FindServerByName(pExtAddTreeNode->Name); LockTreeControl(); CTreeCtrl &tree = GetTreeCtrl(); // First make sure the server isn't already in the tree // Get the first server under the application HTREEITEM hItem = tree.GetNextItem(hParent, 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 CAppServer *pAppServer = (CAppServer*)node->GetTreeObject(); if(pAppServer == (CAppServer*)pExtAddTreeNode->pObject) { UnlockTreeControl(); return 0; } } hItem = tree.GetNextItem(hItem, TVGN_NEXT); } CTreeNode* pNode = new CTreeNode(NODE_APP_SERVER, pExtAddTreeNode->pObject); if(pNode) { HTREEITEM hServer = AddItemToTree(hParent, pExtAddTreeNode->Name, TVI_SORT, DetermineServerIcon(pServer), (DWORD)pNode); if(!hServer) delete pNode; ((CAppServer*)pExtAddTreeNode->pObject)->SetTreeItem(hServer); if(pServer) { // 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); } } UnlockTreeControl(); return 0; } // end CAppTreeView::OnExtAddAppServer //////////////////////////////// // CAppTreeView::OnExtRemoveAppServer // // Message Handler to remove a server from beneath a published application // Pointer to CPublishedApp is in wParam // Pointer to CAppServer is in lParam // LRESULT CAppTreeView::OnExtRemoveAppServer(WPARAM wParam, LPARAM lParam) { ASSERT(wParam); ASSERT(lParam); HTREEITEM hServer = ((CAppServer*)lParam)->GetTreeItem(); if(!hServer) return 0; LockTreeControl(); CTreeCtrl &tree = GetTreeCtrl(); CTreeNode *ServerNode = (CTreeNode*)tree.GetItemData(hServer); // Remove the Users underneath this server in the tree HTREEITEM hUser = tree.GetNextItem(hServer, TVGN_CHILD); while(hUser) { // Get the data attached to the tree item CTreeNode *node = (CTreeNode*)tree.GetItemData(hUser); if(node) { CWinStation *pWinStation = (CWinStation*)node->GetTreeObject(); pWinStation->SetAppTreeItem(NULL); delete node; } hUser = tree.GetNextItem(hUser, TVGN_NEXT); } // Delete the data attached to the tree item delete ServerNode; // Let the AppServer know he is no longer in the tree ((CAppServer*)lParam)->SetTreeItem(NULL); // Remove the AppServer from the tree // This SHOULD remove all it's children GetTreeCtrl().DeleteItem(hServer); UnlockTreeControl(); return 0; } // end CAppTreeView::OnExtRemoveAppServer ///////////////////////////////////////// // CAppTreeView::AddServerChildren // // Adds the Users running the published app on a given Server // to the tree // void CAppTreeView::AddServerChildren(HTREEITEM hServer, CServer *pServer) { ASSERT(hServer); ASSERT(pServer); if(pServer->IsServerSane()) { LockTreeControl(); HTREEITEM hParent = GetTreeCtrl().GetParentItem(hServer); HTREEITEM hLastNode = hServer; CTreeNode *pParentNode = (CTreeNode*)GetTreeCtrl().GetItemData(hParent); CPublishedApp *pApplication = (CPublishedApp*)pParentNode->GetTreeObject(); 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); // We only care if the user is running this published app if(pWinStation->GetState() == State_Active && pWinStation->HasUser() && pWinStation->IsRunningPublishedApp() && pWinStation->IsRunningPublishedApp(pApplication->GetName())) { // Figure out what text to display CString UserString; if(wcslen(pWinStation->GetUserName())) { UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName()); } else UserString.Format(TEXT("%s"), pWinStation->GetName()); CTreeNode *pNode = new CTreeNode(NODE_WINSTATION, pWinStation); if(pNode) { pNode->SetSortOrder(pWinStation->GetSortOrder()); hLastNode = AddItemToTree(hServer, UserString, TVI_SORT, pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNode); if(!hLastNode) delete pNode; } // The WinStation wants to know his tree item handle pWinStation->SetAppTreeItem(hLastNode); } } pServer->UnlockWinStationList(); UnlockTreeControl(); } // end if(pServer->IsServerSane()) } // end CAppTreeView::AddServerChildren //////////////////////////////// // CAppTreeView::OnAdminUpdateServer // // Message handler to update a Server in the tree // Pointer to CServer to update is in lParam // LRESULT CAppTreeView::OnAdminUpdateServer(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); CServer *pServer = (CServer*)lParam; if(!pServer) return 0; LockTreeControl(); // The server can be in the tree more than one place UINT itemCount = GetTreeCtrl().GetCount(); HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem(); for(UINT i = 0; i < itemCount; i++) { CTreeNode *node = ((CTreeNode*)GetTreeCtrl().GetItemData(hTreeItem)); if(node) { // we only care about app servers if(node->GetNodeType() == NODE_APP_SERVER) { CAppServer *pAppServer = (CAppServer*)node->GetTreeObject(); // Is it the same server? if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) { USHORT NewState; // Remember the previous state USHORT PreviousState = GetTreeCtrl().GetItemState(hTreeItem, 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(hTreeItem, 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(hTreeItem, ServerIcon, ServerIcon); AddServerChildren(hTreeItem, pServer); } else if(pServer->GetPreviousState() == SS_DISCONNECTING && pServer->IsState(SS_NOT_CONNECTED)) { int ServerIcon = DetermineServerIcon(pServer); GetTreeCtrl().SetItemImage(hTreeItem, 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 // We also need to make sure this is the currently selected tree CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument(); if(NewState != PreviousState && hTreeItem == GetTreeCtrl().GetSelectedItem() && pDoc->GetCurrentTree() == TREEVIEW_APPS) { #if 0 LONG Result; OnSelChange(NULL, &Result); #endif ForceSelChange(); } } } } hTreeItem = GetNextItem(hTreeItem); } UnlockTreeControl(); return 0; } // end CAppTreeView::OnAdminUpdateServer //////////////////////////////// // CAppTreeView::AddUser // HTREEITEM CAppTreeView::AddUser(CWinStation *pWinStation) { ASSERT(pWinStation); HTREEITEM hWinStation = NULL; // Find the published app that this WinStation is running in our tree CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument(); CPublishedApp *pApplication = pDoc->FindPublishedAppByName(pWinStation->GetPublishedAppName()); CServer *pServer = pWinStation->GetServer(); if(!pApplication) return NULL; HTREEITEM hApplication = pApplication->GetTreeItem(); if(!hApplication) return NULL; CTreeCtrl &tree = LockTreeControl(); // Find this WinStation's server under the published application in the tree HTREEITEM hServer = NULL; hServer = tree.GetChildItem(hApplication); while(hServer) { CTreeNode *pNode = (CTreeNode*)GetTreeCtrl().GetItemData(hServer); CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject(); if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) { // Figure out what text to display CString UserString; if(wcslen(pWinStation->GetUserName())) { UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName()); } else UserString.Format(TEXT("%s"), pWinStation->GetName()); CTreeNode *pNewNode = new CTreeNode(NODE_WINSTATION, pWinStation); if(pNewNode) { hWinStation = AddItemToTree(hServer, UserString, TVI_SORT, pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNewNode); if(!hWinStation) delete pNewNode; // The WinStation wants to know his tree item handle pWinStation->SetAppTreeItem(hWinStation); } } hServer = tree.GetNextSiblingItem(hServer); } UnlockTreeControl(); return hWinStation; } //////////////////////////////// // CAppTreeView::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 CAppTreeView::OnAdminAddWinStation(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); CWinStation *pWinStation = (CWinStation*)lParam; if(!pWinStation) return 0; // If this WinStation isn't running a published App, we // don't give a damn if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp()) return 0; AddUser(pWinStation); return 0; } // end CAppTreeView::OnAdminAddWinStation //////////////////////////////// // CAppTreeView::OnAdminUpdateWinStation // // Message handler to update a WinStation in the tree // lParam = pointer to CWinStation to update // LRESULT CAppTreeView::OnAdminUpdateWinStation(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); CWinStation *pWinStation = (CWinStation*)lParam; if(!pWinStation) return 0; // If this WinStation isn't running a published App, we // don't give a damn if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp()) return 0; // If this WinStation is already in the tree, we don't want to // add it again if(pWinStation->GetAppTreeItem()) return 0; AddUser(pWinStation); return 0; } // end CAppTreeView::OnAdminUpdateWinStation //////////////////////////////// // CAppTreeView::OnAdminRemoveWinStation // // Message handler to remove a WinStation from the tree // lParam = pointer to CWinStation to remove LRESULT CAppTreeView::OnAdminRemoveWinStation(WPARAM wParam, LPARAM lParam) { ASSERT(lParam); BOOL CurrentInTree = FALSE; CWinStation *pWinStation = (CWinStation*)lParam; if(!pWinStation) return 0; HTREEITEM hWinStation = pWinStation->GetAppTreeItem(); if(!hWinStation) return 0; 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; } // Delete the data attached to the tree item delete node; // Let the WinStation know he is no longer in the tree pWinStation->SetAppTreeItem(NULL); // 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! CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument(); if(CurrentInTree && pDoc->GetCurrentTree() == TREEVIEW_APPS) ((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING); UnlockTreeControl(); return 0; } // end CAppTreeView::OnAdminRemoveWinStation //////////////////////////////// // CAppTreeView::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 CAppTreeView::OnContextMenu(CWnd* pWnd, CPoint ptScreen) { CTreeCtrl &tree = GetTreeCtrl(); UINT flags; 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, 0); ptScreen.x = rect.left + (rect.right - rect.left)/2; ptScreen.y = rect.top + (rect.bottom - rect.top)/2; ClientToScreen(&ptScreen); } else { hItem = tree.HitTest(ptClient, &flags); if((NULL == hItem) || !(TVHT_ONITEM & flags)) return; } // Pop-up the menu CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem); CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument(); pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType())); if(pNode) { CMenu menu; UINT nIDResource = 0; switch(pNode->GetNodeType()) { case NODE_APP_SERVER: { CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject(); CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName()); if(pServer) { pDoc->SetTreeTemp(pServer, NODE_SERVER); } else return; nIDResource = IDR_SERVER_POPUP; } break; case NODE_WINSTATION: nIDResource = IDR_WINSTATION_TREE_POPUP; break; } if(nIDResource) { if(menu.LoadMenu(nIDResource)) { menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd()); } } } // end if(pNode) } // end CAppTreeView::OnContextMenu //////////////////////////////// // CAppTreeView::OnRClick // // The Tree Common Control sends a WM_NOTIFY of NM_RCLICK when // the user presses the right mouse button in the tree // void CAppTreeView::OnRClick(NMHDR* pNMHDR, LRESULT* pResult) { CPoint ptScreen(::GetMessagePos()); LockTreeControl(); // Get a pointer to our document CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument(); CTreeCtrl &tree = GetTreeCtrl(); 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 *pDoc = (CWinAdminDoc*)GetDocument(); pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType())); if(pNode) { CMenu menu; UINT nIDResource = 0; switch(pNode->GetNodeType()) { case NODE_APP_SERVER: { CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject(); CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName()); if(pServer) { pDoc->SetTreeTemp(pServer, NODE_SERVER); } else return; nIDResource = IDR_SERVER_POPUP; } break; case NODE_WINSTATION: nIDResource = IDR_WINSTATION_TREE_POPUP; break; } if(nIDResource) { if(menu.LoadMenu(nIDResource)) { menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd()); } } } // end if(pNode) UnlockTreeControl(); } // end CAppTreeView::OnRClick //////////////////////////////// // CAppTreeView::OnLButtonDown // void CAppTreeView::OnLButtonDown(UINT nFlags, CPoint ptClient) { // Figure out what they clicked on LockTreeControl(); CTreeCtrl &tree = GetTreeCtrl(); UINT flags; HTREEITEM hItem; hItem = tree.HitTest(ptClient, &flags); if((NULL == hItem) || !(TVHT_ONITEM & flags)) { UnlockTreeControl(); CTreeView::OnLButtonDown(nFlags, ptClient); return; } // We only care about servers CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem); if(pNode && pNode->GetNodeType() == NODE_APP_SERVER) { // Is it the same item as is selected if(hItem == tree.GetSelectedItem()) { CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject(); CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName()); // Is this server in the "just disconnected" state // 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)) { UnlockTreeControl(); LONG Result; OnSelChange(NULL, &Result); return; } } } UnlockTreeControl(); CTreeView::OnLButtonDown(nFlags, ptClient); } // CAppTreeView::OnLButtonDown