2025-04-27 07:49:33 -04:00

2437 lines
54 KiB
C++

// ***************************************************************************
//
// Copyright (c) 1996-2001 Microsoft Corporation, All Rights Reserved
//
// File: CClassTree.cpp
//
// Description:
// This file implements the CClassTree class which is a part of the Class
// Navigator OCX, it is a subclass of the Microsoft CTreeCtrl common
// control and performs the following functions:
// a. Insertion of individual classes
// b. Allows classes to be "expanded" by going out to the database
// to get its subclasses
// c. Allows classes to be renamed.
// d. Supports operations to add and delete tree branches.
// e. Supports OLE drag and drop (disabled for ALPHA)
//
// Part of:
// ClassNav.ocx
//
// Used by:
//
//
// History:
// Judith Ann Powell 10-08-96 Created.
//
//
// **************************************************************************
// ===========================================================================
//
// Includes
//
// ===========================================================================
#include "precomp.h"
#include "resource.h"
#include "afxpriv.h"
#include "AFXCONV.H"
#include "wbemidl.h"
#include "olemsclient.h"
#include "CClassTree.h"
#include "RenameClassDIalog.h"
#include "TreeDropTarget.h"
#include "CContainedToolBar.h"
#include "Banner.h"
#include "ClassNavCtl.h"
#include "resource.h"
#define KBSelectionTimer 1000
#define ExpansionOrSelectionTimer 1001
#define UPDATESELECTEDITEM WM_USER + 450
#define SELECTITEMONFOCUS WM_USER + 451
void CALLBACK EXPORT SelectItemAfterDelay(HWND hWnd,UINT nMsg, WPARAM nIDEvent, ULONG dwTime)
{
::PostMessage(hWnd,UPDATESELECTEDITEM,0,0);
}
// Only has a valid value for the interval between a double click.
CClassTree *gpTreeTmp;
void CALLBACK EXPORT ExpansionOrSelection(HWND hWnd,UINT nMsg,WPARAM nIDEvent, ULONG dwTime)
{
CClassTree *pTree = gpTreeTmp;
if (!pTree)
{
return;
}
if (pTree->m_uiSelectionTimer)
{
pTree->KillTimer(pTree->m_uiSelectionTimer );
pTree-> m_uiSelectionTimer= 0;
}
if (InterlockedDecrement(&pTree->m_lSelection) == 0)
{
CPoint point(0,0);
pTree->ContinueProcessSelection(TRUE,point );
gpTreeTmp = NULL;
}
}
// ===========================================================================
//
// Message Map
//
// ===========================================================================
BEGIN_MESSAGE_MAP(CClassTree,CTreeCtrl)
ON_WM_CONTEXTMENU()
//{{AFX_MSG_MAP(CClassTree)
ON_WM_CREATE()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_SIZE()
ON_WM_DESTROY()
ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndlabeledit)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginlabeledit)
ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown)
ON_WM_CONTEXTMENU()
ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus)
ON_NOTIFY_REFLECT(NM_SETFOCUS, OnSetfocus)
ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING,OnItemExpanding)
ON_MESSAGE( UPDATESELECTEDITEM,SelectTreeItem)
ON_MESSAGE( SELECTITEMONFOCUS,SelectTreeItemOnFocus)
END_MESSAGE_MAP()
// ***************************************************************************
//
// CClassTree::PreCreateWindow
//
// Description:
// This VIRTUAL member function returns Initializes create struct values
// for the custom tree control.
//
// Parameters:
// CREATESTRUCT& cs A reference to a CREATESTRUCT with default control
// creation values.
//
// Returns:
// BOOL Nonzero if the window creation should continue;
// 0 to indicate creation failure.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
BOOL CClassTree::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CTreeCtrl::PreCreateWindow(cs))
return FALSE;
cs.style = WS_CHILD | WS_VISIBLE | CS_DBLCLKS | TVS_SHOWSELALWAYS |
TVS_HASLINES | TVS_LINESATROOT |TVS_HASBUTTONS;
return TRUE;
}
// ***************************************************************************
//
// CClassTree::CClassTree
//
// Description:
// Class constructor.
//
// Parameters:
// NONE
//
// Returns:
// NONE
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
CClassTree::CClassTree()
: m_bInDrag (FALSE),
m_prevDropEffect (DROPEFFECT_NONE),
m_bDropTargetRegistered (FALSE),
m_bDragAndDropState (FALSE),
m_dragSize (1,1),
m_dragPoint (-1,-1),
m_lClickTime(0),
m_bDeleting(FALSE),
m_bMouseDown(FALSE),
m_bKeyDown(FALSE),
m_uiTimer(0),
m_bFirstSetFocus(TRUE),
m_bUseItem(FALSE),
m_hItemToUse(NULL)
{
}
//============================================================================
//
// CClassTree::InitTreeState
//
// Description:
// This function initializes processing state for the custom tree control.
//
// Parameters:
// CClassNavCtrl *pParent A CClassNavCtrl pointer to the tree controls
// parent window.
//
// Returns:
// VOID .
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
//============================================================================
void CClassTree::InitTreeState (CClassNavCtrl *pParent)
{
if (m_uiTimer)
{
KillTimer( m_uiTimer );
m_uiTimer = 0;
}
m_bMouseDown = FALSE;
m_bKeyDown = FALSE;
m_bUseItem = FALSE;
m_hItemToUse = NULL;
m_pParent = pParent;
}
// ***************************************************************************
//
// CClassTree::AddTreeObject
//
// Description:
// Adds an IWbemClassObject instance to the tree.
//
// Parameters:
// HTREEITEM hParent Tree item parent.
// IWbemClassObject *pimcoNew Class object
// BOOL bNewClass If a new class add to tree and class
// roots.
//
// Returns:
// HTREEITEM Tree item handle of added class.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
HTREEITEM CClassTree::AddNewClass(HTREEITEM hParent,IWbemClassObject *pimcoNew)
{
CSchemaInfo::CClassInfo &info= m_schema.AddClass(pimcoNew);
HTREEITEM hObject = AddTreeObject2(hParent, info);
if (hObject)
EnsureVisible(hObject);
// Update parent's icons
if(hParent)
RefreshIcons(hParent);
else
{
m_pParent->GetTreeRoots()->Add(hObject);
m_pParent->GetClassRoots()->Add(pimcoNew);
}
return hObject;
}
void CClassTree::RefreshIcons(HTREEITEM hItem)
{
while(hItem)
{
int nImage = m_schema[GetItemText(hItem)].GetImage();
SetItemImage(hItem, nImage, nImage);
hItem = GetParentItem(hItem);
}
}
HTREEITEM CClassTree::AddTreeObject2(HTREEITEM hParent, CSchemaInfo::CClassInfo &info)
{
HTREEITEM hObject = NULL;
int nImage = info.GetImage();
hObject = InsertTreeItem(hParent, (LPARAM) info.m_pObject, nImage, nImage, info.m_szClass, FALSE, info.m_rgszSubs.GetSize()>0);
return hObject;
}
// ***************************************************************************
//
// CClassTree::OnItemExpanding
//
// Description:
// Special processing associated with expanding or callapsing a
// tree branch.
//
// Parameters:
// NMHDR *pNMHDR Notification message structure.
// LRESULT *pResult Set to TRUE to prevent the list from
// expanding or collapsing.
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnItemExpanding
(NMHDR *pNMHDR, LRESULT *pResult)
{
SetFocus();
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hItem = pnmtv->itemNew.hItem;
*pResult = 0;
m_pParent -> InvalidateControl();
}
// ***************************************************************************
//
// CClassTree::InsertTreeItem
//
// Description:
// Construct TV_INSERTSTRUCT for insertion into the CTreeCtrl and insert
// item.
//
// Parameters:
// HTREEITEM hParent Parent tree item.
// LPARAM lparam Data to store in tree item data.
// int iBitmap Index to bitmap.
// int iSelectedBitmap Index to selected bitmap.
// LPCTSTR pszText Tree item label.
// BOOL bBold If TRUE label in bold.
// BOOL bChildren If TRUE tree item has children.
//
// Returns:
// HTREEITEM Tree item handle of new item.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
HTREEITEM CClassTree::InsertTreeItem
(HTREEITEM hParent, LPARAM lparam, int iBitmap, int iSelectedBitmap,
LPCTSTR pszText, BOOL bBold, BOOL bChildren)
{
// If we are in select all mode we open the tree items
// with a check (see tvis.item.state)
TVINSERTSTRUCT tvis;
tvis.hParent = hParent;
tvis.hInsertAfter = TVI_LAST;
tvis.item.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM | TVIF_IMAGE | TVIF_STATE;
tvis.item.cChildren = bChildren?1:0;
tvis.item.pszText = (LPTSTR) pszText;
tvis.item.iImage = iBitmap;
tvis.item.iSelectedImage = iBitmap;
tvis.item.state = INDEXTOSTATEIMAGEMASK((m_pParent->m_bSelectAllMode)?2:1);;
tvis.item.stateMask = TVIS_STATEIMAGEMASK;
tvis.item.lParam = lparam;
return InsertItem(&tvis);
}
// ***************************************************************************
//
// CClassTree::OnRButtonDown
//
// Description:
// Do not pass on to the base class so the context menu can be
// invoked.
//
// Parameters:
// UINT nFlags Indicates whether various virtual keys are down.
// CPoint point Specifies the x and y coordinates of the cursor.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnRButtonDown(UINT nFlags, CPoint point)
{
// Do not want to pass on to tree control.
UINT hitFlags ;
HTREEITEM hItem ;
hItem = HitTest( point, &hitFlags ) ;
if (hitFlags & (TVHT_ONITEM | TVHT_ONITEMBUTTON))
{
// m_pParent->m_hContextSelection = hItem;
}
else
{
// m_pParent->m_hContextSelection = NULL;
}
}
// ***************************************************************************
//
// CClassTree::OnContextMenu
//
// Description:
// Initialize the context menu. See PSS ID Q141199.
//
// Parameters:
// CWnd* pWnd CWnd parent.
// CPoint point Specifies the x and y coordinates of the cursor.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnContextMenu(CWnd* pWnd, CPoint point)
{
// CG: This function was added by the Pop-up Menu component
// See for PSS ID Number: Q141199 for explanation of modifications
// required for COleControl
UINT hitFlags ;
HTREEITEM hItem ;
CPoint cpClient;
if (point.x == -1 && point.y == -1)
{
CRect crClient;
GetClientRect(&crClient);
hItem = GetSelectedItem();
if (hItem)
{
RECT rect;
BOOL bRect = GetItemRect(hItem,&rect, TRUE );
POINT p;
p.x = rect.left + 2;
p.y = rect.top + 2;
if (bRect && crClient.PtInRect(p))
{
cpClient.x = rect.left + 2;
cpClient.y = rect.top + 2;
}
else
{
cpClient.x = 0;
cpClient.y = 0;
}
}
m_pParent->m_hContextSelection = hItem;
point = cpClient;
ClientToScreen(&point);
}
else
{
cpClient = point;
ScreenToClient(&cpClient);
hItem = HitTest( cpClient, &hitFlags ) ;
if (hitFlags & (TVHT_ONITEM | TVHT_ONITEMBUTTON))
{
m_pParent->m_hContextSelection = hItem;
}
else
{
m_pParent->m_hContextSelection = NULL;
}
}
VERIFY(m_cmContext.LoadMenu(CG_IDR_POPUP_A_TREE_CTRL));
CMenu* pPopup = m_cmContext.GetSubMenu(0);
CWnd* pWndPopupOwner = m_pParent;
HWND hwndFocus = ::GetFocus();
pPopup->TrackPopupMenu
(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
pWndPopupOwner);
m_cmContext.DestroyMenu();
if (::IsWindow(hwndFocus) && ::IsWindowVisible(hwndFocus)) {
::SetFocus(hwndFocus);
}
}
// ***************************************************************************
//
// CClassTree::OnCreate
//
// Description:
// Called by the framework after the window is being created but before
// the window is shown.
//
// Parameters:
// LPCREATESTRUCT lpCreateStruct Pointer to the structure which contains
// default parameters.
//
// Returns:
// BOOL 0 if continue; -1 if the window should be destroyed.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
int CClassTree::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
m_uTreeCF = RegisterClipboardFormat(_T("ATREECONTROL_CF"));
return 0;
}
// ***************************************************************************
//
// CClassTree::OnLButtonDown
//
// Description:
// Process things that need to happen on a left button down.
//
// Parameters:
// UINT nFlags Indicates whether various virtual keys are down.
// CPoint point Specifies the x and y coordinates of the cursor.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnLButtonDown(UINT nFlags, CPoint point)
{
UINT m_nLBDFlags;
CPoint m_cpLBDPoint = point;
HTREEITEM hItem = HitTest( m_cpLBDPoint, &m_nLBDFlags ) ;
// Toggle tree item image if the state icon was selected.
if (hItem && (m_nLBDFlags & (TVHT_ONITEMSTATEICON)) )
{
UINT nStateMask = TVIS_STATEIMAGEMASK;
UINT uState =
GetItemState( hItem, nStateMask );
UINT uImage1 = INDEXTOSTATEIMAGEMASK (1);
UINT uImage2 = INDEXTOSTATEIMAGEMASK (2);
if (uState & INDEXTOSTATEIMAGEMASK (1))
{
uState = INDEXTOSTATEIMAGEMASK (2);
}
else
{
if (m_pParent->m_bSelectAllMode)
{
m_pParent->m_bItemUnselected = TRUE;
}
else
{
m_pParent->m_bItemUnselected = FALSE;
}
uState = INDEXTOSTATEIMAGEMASK (1);
}
SetItemState(hItem, uState, TVIS_STATEIMAGEMASK);
}
CTreeCtrl::OnLButtonDown(nFlags, point);
}
// ***************************************************************************
//
// CClassTree::OnLButtonUp
//
// Description:
// Process things that need to happen on a left button up.
//
// Parameters:
// UINT nFlags Indicates whether various virtual keys are down.
// CPoint point Specifies the x and y coordinates of the cursor.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bMouseDown = TRUE;
m_bKeyDown = FALSE;
CTreeCtrl::OnLButtonUp(nFlags, point);
m_pParent -> OnActivateInPlace(TRUE,NULL);
}
// ***************************************************************************
//
// CClassTree::OnMouseMove
//
// Description:
// Process things that need to happen when the mouse moves.
//
// Parameters:
// UINT nFlags Indicates whether various virtual keys are down.
// CPoint point Specifies the x and y coordinates of the cursor.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bInDrag)
{
CTreeCtrl::OnMouseMove(nFlags, point);
return;
}
if ((nFlags & MK_LBUTTON) == MK_LBUTTON)
{
UINT m_nLBDFlags;
CPoint m_cpLBDPoint = point;
HTREEITEM hItem = HitTest( m_cpLBDPoint, &m_nLBDFlags ) ;
m_bInDrag = TRUE; // This disables beginning a drag
// Maybe will be enabled post alpha
return;
}
CTreeCtrl::OnMouseMove(nFlags, point);
}
// ***************************************************************************
//
// CClassTree::OnSelchanged
//
// Description:
// Process things that need to happen when the selected tree item
// has changed.
//
// Parameters:
// NMHDR *pNMHDR Notification message structure.
// LRESULT *pResult Set to TRUE to prevent the selection from
// changing.
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
m_pParent -> PostMessage(SETFOCUSTREE,0,0);
}
void CClassTree::ContinueProcessSelection(UINT nFlags, CPoint point)
{
if (m_pParent->m_bOpeningNamespace)
{
return;
}
UINT uFlags = 0;
HTREEITEM hItem;
if (m_bUseItem)
{
hItem = m_hItemToUse;
m_bUseItem = FALSE;
m_hItemToUse = NULL;
}
else
{
hItem= HitTest( point, &uFlags );
}
if (!hItem || m_bKeyDown)
{
m_bUseItem = FALSE;
m_hItemToUse = NULL;
m_pParent -> PostMessage(SETFOCUSTREE,0,0);
return;
}
IWbemClassObject *pItem = reinterpret_cast<IWbemClassObject *>(GetItemData(hItem));
if (m_bUseItem)
{
m_bUseItem = FALSE;
m_hItemToUse = NULL;
}
if (!pItem)
{
m_pParent -> PostMessage(SETFOCUSTREE,0,0);
return;
}
CString csClass = _T("__Class");
m_csSelection = ::GetProperty(pItem, &csClass);
if (m_csSelection[0] == '_' && m_csSelection[1] == '_')
{
// Disable the delete button.
m_pParent->m_cbBannerWindow.m_cctbToolBar.
GetToolBarCtrl().EnableButton(ID_BUTTONDELETE,FALSE);
m_pParent->m_cbBannerWindow.m_cctbToolBar.
GetToolBarCtrl().EnableButton(ID_BUTTONADD,TRUE);
}
else
{
m_pParent->m_cbBannerWindow.m_cctbToolBar.
GetToolBarCtrl().EnableButton(ID_BUTTONDELETE,TRUE);
m_pParent->m_cbBannerWindow.m_cctbToolBar.
GetToolBarCtrl().EnableButton(ID_BUTTONADD,TRUE);
}
if (!m_bDeleting)
{
CString csItem;
COleVariant covClass;
// Fire events.
csItem = GetIWbemFullPath(m_pParent->GetServices(),pItem);
covClass = csItem;
if (!m_pParent->m_bOpenedInitialNamespace)
{
m_pParent->m_bOpenedInitialNamespace = TRUE;
if (m_pParent->m_bReadySignal)
{
m_pParent->FireNotifyOpenNameSpace(m_pParent->m_csNameSpace);
}
}
#ifdef _DEBUG
afxDump <<"CClassTree::OnSelchanged: Before m_pParent -> FireEditExistingClass(covNewClass); \n";
afxDump << " " << csItem << "\n";
#endif
if (m_pParent->m_bReadySignal)
{
m_pParent -> FireEditExistingClass(covClass);
}
#ifdef _DEBUG
afxDump <<"CClassTree::OnSelchanged: After m_pParent -> FireEditExistingClass(covNewClass); \n";
afxDump << " " << csItem << "\n";
#endif
}
m_pParent -> PostMessage(SETFOCUSTREE,0,0);
}
// ***************************************************************************
//
// CClassTree::OnHScroll
//
// Description:
// Process things that need to happen when the tree has been scrolled.
//
// Parameters:
// UINT nSBCode Scroll-bar code for scrolling request.
// UINT nPos Scroll-box position.
// CScrollBar* pScrollBar Scroll bar control or NULL.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}
// ***************************************************************************
//
// CClassTree::OnVScroll
//
// Description:
// Process things that need to happen when the tree has been scrolled.
//
// Parameters:
// UINT nSBCode Scroll-bar code for scrolling request.
// UINT nPos Scroll-box position.
// CScrollBar* pScrollBar Scroll bar control or NULL.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
// ***************************************************************************
//
// CClassTree::OnSize
//
// Description:
// Called by the framework after the window is being resized.
//
// Parameters:
// UINT nType Specifies the type of resizing requested.
// int cx Specifies the new width of the client area.
// int cy Specifies the new height of the client area.
//
// Returns:
// void
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnSize(UINT nType, int cx, int cy)
{
CTreeCtrl::OnSize(nType, cx, cy);
}
// ***************************************************************************
//
// CClassTree::OnDestroy
//
// Description:
// Process things that need to happen when the tree is going away,
// before the tree is actually destroyed. Is is no longer visible
// but still exists.
//
// Parameters:
// NONE
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnDestroy()
{
if (m_uiTimer)
{
KillTimer( m_uiTimer );
m_uiTimer = 0;
}
m_bMouseDown = FALSE;
m_bKeyDown = FALSE;
m_bUseItem = FALSE;
m_hItemToUse = NULL;
CPtrArray *pcpaTreeRoots = m_pParent -> GetTreeRoots();
int nRoots = (int) pcpaTreeRoots -> GetSize( );
HTREEITEM hItem;
for (int i = 0; i < nRoots; i++)
{
hItem =
reinterpret_cast<HTREEITEM>(pcpaTreeRoots -> GetAt(i));
if (hItem)
{
ReleaseClassObjects(hItem);
}
}
CTreeCtrl::OnDestroy();
}
// ***************************************************************************
//
// CClassTree::GetSelectionPath
//
// Description:
// Returns a CString which contains the current tree selection.
//
// Parameters:
// VOID
//
// Returns:
// CString Full path of selection.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
CString CClassTree::GetSelectionPath(HTREEITEM hIn)
{
CString csPath = _T("");
HTREEITEM hItem = hIn ? hIn :GetSelectedItem();
if (hItem)
{
IWbemClassObject *pimcoSel =
reinterpret_cast<IWbemClassObject *>
(GetItemData(hItem));
if (pimcoSel)
{
csPath = GetIWbemFullPath
(NULL, pimcoSel);
}
}
return csPath;
}
// ***************************************************************************
//
// CClassTree::NumExtendedSelection
//
// Description:
// Returns the number of extended selections for specified state.
//
// Parameters:
// int nState Selected or not selected
//
// Returns:
// int Number of items with state.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
int CClassTree::NumExtendedSelection(int nState)
{
CPtrArray cpaExtendedSelection;
int nExtendedSelection =
ExtendedSelectionFromTree(cpaExtendedSelection,nState);
CString *pcs;
for (int i = 0; i < nExtendedSelection; i++)
{
pcs = reinterpret_cast<CString *>
(cpaExtendedSelection.GetAt(i));
delete pcs;
}
return nExtendedSelection;
}
// ***************************************************************************
//
// CClassTree::GetExtendedSelection
//
// Description:
// Return a SAFEARRAY which contains the class names of classes selected
// via the extended selection mechanism. [Extended selection is via
// selection of the tree items icon.]
//
// Parameters:
// int nState Selected or not selected
//
// Returns:
// SAFEARRAY * Of type VT_BSTR
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
SAFEARRAY *CClassTree::GetExtendedSelection(int nState)
{
SAFEARRAY *psaSelections;
int i;
CPtrArray cpaExtendedSelection;
int nExtendedSelection =
ExtendedSelectionFromTree(cpaExtendedSelection,nState);
if (nExtendedSelection == 0)
{
MakeSafeArray (&psaSelections, VT_BSTR, 1);
PutStringInSafeArray (psaSelections, &m_pParent->m_csNameSpace, 0);
}
else
{
MakeSafeArray (&psaSelections, VT_BSTR, nExtendedSelection + 1);
int n = 0;
PutStringInSafeArray (psaSelections, &m_pParent->m_csNameSpace , n++);
for (i = 0; i < nExtendedSelection; i++)
{
CString *pcs =
reinterpret_cast<CString *>(cpaExtendedSelection.GetAt(i));
PutStringInSafeArray (psaSelections, pcs , n++);
}
}
int nSelections = (int) cpaExtendedSelection.GetSize( );
CString *pcs;
for (i = 0; i < nSelections; i++)
{
pcs = reinterpret_cast<CString *>
(cpaExtendedSelection.GetAt(i));
delete pcs;
}
return psaSelections;
}
// ***************************************************************************
//
// CClassTree::ExtendedSelectionFromTree
//
// Description:
// Return a CPtrArray which contains the class names of classes selected
// via the extended selection mechanism with state (either selected or not
// selected. For whole tree.
//
// Parameters:
// CPtrArray &cpaExtendedSelection The items with state.
// int nState Selected or not selected
//
// Returns:
// int Number of items with state in tree.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
int CClassTree::ExtendedSelectionFromTree
(CPtrArray &cpaExtendedSelection,int nState)
{
CPtrArray *pcpaTreeRoots = m_pParent -> GetTreeRoots();
int nRoots = (int) pcpaTreeRoots -> GetSize( );
HTREEITEM hItem;
for (int i = 0; i < nRoots; i++)
{
hItem =
reinterpret_cast<HTREEITEM>(pcpaTreeRoots -> GetAt(i));
if (hItem)
{
ExtendedSelectionFromRoot(hItem,cpaExtendedSelection,nState);
}
}
return (int) cpaExtendedSelection.GetSize( );
}
// ***************************************************************************
//
// CClassTree::ExtendedSelectionFromRoot
//
// Description:
// Return a CPtrArray which contains the class names of classes selected
// via the extended selection mechanism with state (either selected or not
// selected. For a branch.
//
// Parameters:
// HTREEITEM hItem Branch root to get selection from.
// CPtrArray &cpaExtendedSelection The items with state.
// int nState Selected or not selected
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::ExtendedSelectionFromRoot
(HTREEITEM hItem, CPtrArray &cpaExtendedSelection, int nState)
{
UINT nStateMask = TVIS_STATEIMAGEMASK;
UINT uState =
GetItemState( hItem, nStateMask );
if (uState & INDEXTOSTATEIMAGEMASK (nState))
{
IWbemClassObject *pItem = (IWbemClassObject*) GetItemData(hItem) ;
if (pItem)
{
CString csClass = _T("__Path");
csClass = ::GetProperty(pItem, &csClass);
CString *pcsClass = new CString(csClass);
cpaExtendedSelection.Add
(reinterpret_cast<void *>(pcsClass));
}
}
// now rip thru the children
if (!ItemHasChildren (hItem))
{
return ;
}
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
ExtendedSelectionFromRoot(hChild, cpaExtendedSelection,nState);
hChild = GetNextSiblingItem(hChild);
}
return;
}
// ***************************************************************************
//
// CClassTree::ClearExtendedSelection
//
// Description:
// Clears extended selection for the whole tree.
//
// Parameters:
// NONE
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::ClearExtendedSelection()
{
CPtrArray *pcpaTreeRoots = m_pParent -> GetTreeRoots();
int nRoots = (int) pcpaTreeRoots -> GetSize( );
HTREEITEM hItem;
for (int i = 0; i < nRoots; i++)
{
hItem =
reinterpret_cast<HTREEITEM>(pcpaTreeRoots -> GetAt(i));
if (hItem)
{
ClearExtendedSelectionFromRoot(hItem);
}
}
m_pParent -> InvalidateControl();
}
// ***************************************************************************
//
// CClassTree::ClearExtendedSelection
//
// Description:
// Clears extended selection for a branch.
//
// Parameters:
// HTREEITEM hItem Branch root to clear selection from.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::ClearExtendedSelectionFromRoot
(HTREEITEM hItem)
{
UINT nStateMask = TVIS_STATEIMAGEMASK;
UINT uState =
GetItemState( hItem, nStateMask );
if (uState & INDEXTOSTATEIMAGEMASK (2))
{
SetItemState(hItem, INDEXTOSTATEIMAGEMASK (1), TVIS_STATEIMAGEMASK);
}
// now rip thru the children
if (!ItemHasChildren (hItem))
{
return ;
}
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
ClearExtendedSelectionFromRoot(hChild);
hChild = GetNextSiblingItem(hChild);
}
return;
}
// ***************************************************************************
//
// CClassTree::SetExtendedSelection
//
// Description:
// Sets extended selection for the whole tree.
//
// Parameters:
// NONE
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::SetExtendedSelection()
{
CPtrArray *pcpaTreeRoots = m_pParent -> GetTreeRoots();
int nRoots = (int) pcpaTreeRoots -> GetSize( );
HTREEITEM hItem;
for (int i = 0; i < nRoots; i++)
{
hItem =
reinterpret_cast<HTREEITEM>(pcpaTreeRoots -> GetAt(i));
if (hItem)
{
SetExtendedSelectionFromRoot(hItem);
}
}
m_pParent -> InvalidateControl();
}
// ***************************************************************************
//
// CClassTree::SetExtendedSelectionFromRoot
//
// Description:
// Sets extended selection for a branch.
//
// Parameters:
// HTREEITEM hItem Branch root to set selection for.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::SetExtendedSelectionFromRoot
(HTREEITEM hItem)
{
SetItemState(hItem, INDEXTOSTATEIMAGEMASK (2), TVIS_STATEIMAGEMASK);
// now rip thru the children
if (!ItemHasChildren (hItem))
{
return ;
}
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
SetExtendedSelectionFromRoot(hChild);
hChild = GetNextSiblingItem(hChild);
}
return;
}
// ***************************************************************************
//
// CClassTree::OnItemexpanded
//
// Description:
// Invoked to let the tree know one of its tree items has been
// expanded or contracted.
//
// Parameters:
// NMHDR *pNMHDR Notification message structure.
// LRESULT *pResult Return value ignored.
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
*pResult = 0;
}
// ***************************************************************************
//
// CClassTree::FindObjectinChildren
//
// Description:
// Finds the tree item in a branch that represents a class object
//
// Parameters:
// HTREEITEM hItem Root of branch
// IWbemClassObject *pClassObject Class to search for.
//
// Returns:
// HTREEITEM Tree item; or NULL if not found.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
HTREEITEM CClassTree::FindObjectinChildren
(HTREEITEM hItem, IWbemClassObject *pClassObject)
{
HTREEITEM hChild = GetChildItem(hItem);
if (!hChild)
{
return NULL;
}
IWbemClassObject *pChild;
while (hChild)
{
pChild =
reinterpret_cast<IWbemClassObject *>
(GetItemData(hChild));
if (ClassIdentity(pClassObject,pChild))
{
return hChild;
}
hChild = GetNextSiblingItem(hChild);
}
return NULL;
}
// ***************************************************************************
//
// CClassTree::OnEndlabeledit
//
// Description:
// Invoked to let the tree know one of its tree item labels
// has been changed. Semantics for us is a class rename.
//
// Parameters:
// NMHDR *pNMHDR Notification message structure.
// LRESULT *pResult Set to FALSE to prevent the label from
// changing; otherwise non-zero.
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
HTREEITEM hItem = pTVDispInfo -> item.hItem;
UpdateItemData(hItem);
IWbemClassObject *pimcoEdit =
reinterpret_cast<IWbemClassObject *>(GetItemData(hItem));
CString csClass = _T("__Class");
CString csClassName = pimcoEdit ? ::GetProperty
(pimcoEdit, &csClass) : "";
CString csNew = pTVDispInfo -> item.pszText;
if (csNew.GetLength() == 0)
{
*pResult = 0;
SelectItem(hItem); // 1-29-99
SetFocus(); // 1-29-99
return;
}
// Check to see if the class already exists
IWbemClassObject *pimcoMaybe = NULL;
BSTR bstrTemp = csNew.AllocSysString();
SCODE sc = m_pParent -> GetServices() ->
GetObject(bstrTemp, 0, NULL, &pimcoMaybe, NULL);
::SysFreeString(bstrTemp);
// Class already exists so cannot rename.
if (pimcoMaybe && sc == S_OK)
{
CString csUserMsg =
_T("An error occured renaming a class: ");
csUserMsg +=
_T("The class already exists.");
ErrorMsg
(&csUserMsg, sc, NULL, TRUE, &csUserMsg, __FILE__, __LINE__ - 11);
pimcoMaybe -> Release();
*pResult = 0;
SelectItem(hItem); // 1-29-99
SetFocus(); // 1-29-99
return;
}
// Must delete pimcoEdit after its children have been
// reparented.
IWbemClassObject *pimcoNew =
RenameAClass
(m_pParent -> GetServices(), pimcoEdit, &csNew, FALSE);
if (!pimcoNew)
{
CString csUserMsg =
_T("Cannot rename class: ") + csClassName;
ErrorMsg
(&csUserMsg, S_OK, NULL, TRUE, &csUserMsg, __FILE__, __LINE__ - 7);
SelectItem(hItem); // 1-29-99
SetFocus(); // 1-29-99
*pResult = 0; // 1-29-99
return;
}
csClass = GetIWbemFullPath(m_pParent->GetServices(),pimcoNew);
COleVariant covClass(csClass);
if (m_pParent->m_bReadySignal)
{
m_pParent -> FireEditExistingClass(covClass);
}
#ifdef _DEBUG
afxDump <<"CBanner::OnEndlabeledit: m_pParent -> FireEditExistingClass(covNewClass); \n";
afxDump << " " << csClass << "\n";
#endif
pimcoEdit->Release();
SetItemData(hItem,(LPARAM)(pimcoNew));
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
IWbemClassObject *pimcoChild
= reinterpret_cast<IWbemClassObject *>(GetItemData(hChild));
ReparentAClass(m_pParent -> GetServices(),pimcoNew, pimcoChild);
hChild = GetNextSiblingItem(hChild);
}
BOOL bReturn = DeleteAClass
(m_pParent -> GetServices(), &csClassName );
SelectItem(hItem); // 1-29-99
SetFocus(); // 1-29-99
*pResult = 1;
}
void CClassTree::UpdateItemData(HTREEITEM hItem)
{
IWbemClassObject *pimcoItemData =
reinterpret_cast<IWbemClassObject *>(GetItemData(hItem));
if (!pimcoItemData)
{
return;
}
CString csClass = GetIWbemClass(pimcoItemData);
pimcoItemData->Release();
pimcoItemData = NULL;
pimcoItemData = GetClassObject
(m_pParent -> GetServices(),&csClass,FALSE);
if (!pimcoItemData)
{
return;
}
SetItemData(hItem,(LPARAM)(pimcoItemData));
}
// ***************************************************************************
//
// CClassTree::OnBeginlabeledit
//
// Description:
// Invoked to let the tree know one of its tree item labels
// is being changed. Semantics for us is a class rename.
//
// Parameters:
// NMHDR *pNMHDR Notification message structure.
// LRESULT *pResult Set to non-zero to prevent the label from
// being edited; otherwise zero.
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
HTREEITEM hSelection = GetSelectedItem( );
if (hSelection)
{
CString csSelection = GetSelectionPath(hSelection);
BOOL bCanChangeSelection = m_pParent->QueryCanChangeSelection(csSelection);
if (!bCanChangeSelection)
{
SetFocus();
*pResult = 1;
return;
}
}
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
HTREEITEM hItem = pTVDispInfo -> item.hItem;
IWbemClassObject *pimcoEdit =
reinterpret_cast<IWbemClassObject *>(GetItemData(hItem));
if (!pimcoEdit)
{
*pResult = 1;
return;
}
CString csClass = _T("__Class");
m_csSelection = ::GetProperty(pimcoEdit, &csClass);
if (m_csSelection[0] == '_' && m_csSelection[1] == '_')
{
*pResult = 1;
CString csPrompt =
_T("You cannot rename a system class.");
int nReturn =
m_pParent -> MessageBox
(
csPrompt,
_T("Class Rename Error"),
MB_OK | MB_ICONSTOP | MB_DEFBUTTON1 |
MB_APPLMODAL);
SetFocus();
return;
}
if (ItemHasChildren(hItem))
{
*pResult = 1;
CString csPrompt =
_T("You cannot rename a class which has subclasses.");
int nReturn =
m_pParent -> MessageBox
(
csPrompt,
_T("Class Rename Error"),
MB_OK | MB_ICONSTOP | MB_DEFBUTTON1 |
MB_APPLMODAL);
SetFocus();
return;
}
else
{
BOOL bSubClasses =
HasSubclasses
(m_pParent->GetServices(), pimcoEdit,m_pParent->m_csNameSpace);
if (bSubClasses)
{
*pResult = 1;
return;
}
else
{
BOOL bReturn;
CString csQual = _T("dynamic");
SCODE sc =
GetAttribBool
(pimcoEdit,NULL, &csQual,bReturn);
CString csProvider;
CString csPrompt;
if (bReturn)
{
csQual = _T("provider");
sc =
GetAttribBSTR
(pimcoEdit,NULL, &csQual, csProvider);
csPrompt =
_T("The dynamic provider for this class \"");
csPrompt += csProvider + _T("\"");
csPrompt += _T(" may need to be updated. Do you want to continue renaming the class?");
}
else
{
csPrompt =
_T("If this class has static instances renaming the class will result in the instances being deleted. Do you want to continue renaming the class?");
}
int nReturn =
m_pParent -> MessageBox
(
csPrompt,
_T("Class Rename Warning"),
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1 |
MB_APPLMODAL);
SetFocus();
if (nReturn == IDYES)
{
*pResult = 0;
}
else
{
*pResult = 1;
}
}
}
}
// ***************************************************************************
//
// CClassTree::FindAndOpenObject
//
// Description:
// Find an object in the tree or grow the tree to object.
//
// Parameters:
// IWbemClassObject *pClass Class object;
//
// Returns:
// HTREEITEM Tree item or NULL.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
HTREEITEM CClassTree::FindAndOpenObject(IWbemClassObject *pClass)
{
CString csClass = _T("__Class");
csClass = ::GetProperty(pClass,&csClass);
CStringArray *pcsaPath = PathFromRoot (pClass);
HTREEITEM hRoot;
HTREEITEM hItem = NULL;
if (pcsaPath->GetSize() > 1)
{
HTREEITEM hChild;
hChild = hRoot =
m_pParent->FindObjectinClassRoots
(&pcsaPath->GetAt(0));
for (int i = 1; i < pcsaPath->GetSize(); i++)
{
IWbemClassObject *pObject = NULL;
IWbemClassObject *pErrorObject = NULL;
BSTR bstrTemp = pcsaPath->GetAt(i).AllocSysString();
SCODE sc =
m_pParent->GetServices() -> GetObject
(bstrTemp,0,
NULL, &pObject, NULL);
::SysFreeString(bstrTemp);
if (sc == S_OK)
{
hChild =
FindObjectinChildren
(hRoot, pObject);
if (hChild)
{
hRoot = hChild;
}
else
{
Expand(hRoot,TVE_EXPAND);
hRoot = hChild =
FindObjectinChildren
(hRoot, pObject);
}
ReleaseErrorObject(pErrorObject);
pObject ->Release();
}
else
{
ErrorMsg
(NULL, sc, pErrorObject, TRUE, NULL, __FILE__, __LINE__ - 40);
ReleaseErrorObject(pErrorObject);
}
}
hItem = hChild;
}
else
{
hRoot =
m_pParent->FindObjectinClassRoots
(&csClass);
hItem = hRoot;
}
delete pcsaPath;
if (hItem)
{
SelectSetFirstVisible(hItem);
SelectItem(hItem);
SetFocus();
Expand(hItem,TVE_EXPAND);
}
return hItem;
}
BOOL CClassTree::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
return TRUE;
}
DROPEFFECT CClassTree::OnDropEx(COleDataObject* pDataObject, DROPEFFECT dropEffect, DROPEFFECT dropEffectList, CPoint point)
{
return DROPEFFECT_NONE;
}
DROPEFFECT CClassTree::OnDragEnter(COleDataObject* pDataObject, DWORD grfKeyState, CPoint point)
{
return DROPEFFECT_NONE;
}
DROPEFFECT CClassTree::OnDragOver(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point)
{
return DROPEFFECT_NONE;
}
DROPEFFECT CClassTree::OnDragScroll(DWORD grfKeyState, CPoint point)
{
return DROPEFFECT_NONE;
}
void CClassTree::OnDragLeave()
{
}
// ***************************************************************************
//
// CClassTree::IsChildNodeOf
//
// Description:
// Predicate to see if a tree item is a parent or grand ... parent
// of a another tree item.
//
// Parameters:
// HTREEITEM hitemChild Item to test.
// HTREEITEM hitemSuspectedParent Maybe a parent.
//
// Returns:
// BOOL TRUE if a child; otherwise FALSE
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
BOOL CClassTree::IsChildNodeOf
(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
{
do
{
if (hitemChild == hitemSuspectedParent)
break;
}
while ((hitemChild = GetParentItem(hitemChild)) != NULL);
return (hitemChild != NULL);
}
// ***************************************************************************
//
// CClassTree::DeleteBranch
//
// Description:
// Delete a branch of the tree and conditionally release the
// class objects assoiciated with the tree items.
//
// Parameters:
// HTREEITEM hItem Root of branch to transfer.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::DeleteBranch(HTREEITEM &hItem)
{
HTREEITEM hParent = GetParentItem(hItem);
IWbemClassObject *pClassObject;
pClassObject
= reinterpret_cast<IWbemClassObject *>
(GetItemData( hItem ));
if (!hParent) // item is a root
{
if (pClassObject)
{
m_pParent -> RemoveObjectFromClassRoots(pClassObject);
}
m_pParent -> RemoveItemFromTreeItemRoots(hItem);
}
if (pClassObject)
{
pClassObject -> Release();
}
if (!ItemHasChildren (hItem))
{
DeleteItem(hItem);
HTREEITEM hChild = NULL;
hChild = GetChildItem(hParent);
if (!hChild)
{
TV_INSERTSTRUCT tvstruct;
tvstruct.item.hItem = hParent;
tvstruct.item.mask = TVIF_CHILDREN | TVIF_STATE;
tvstruct.item.stateMask = TVIS_EXPANDEDONCE;
tvstruct.item.state = TVIS_EXPANDEDONCE;
tvstruct.item.cChildren = 0;
SetItem(&tvstruct.item);
EnsureVisible (hParent); // 10-26-96 force parent to update
}
hItem = 0;
return;
}
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
DeleteBranch(hChild);
if (hChild)
hChild = GetNextSiblingItem(hChild);
}
DeleteItem(hItem);
hChild = NULL;
hChild = GetChildItem(hParent);
if (!hChild)
{
TV_INSERTSTRUCT tvstruct;
tvstruct.item.hItem = hParent;
tvstruct.item.mask = TVIF_CHILDREN | TVIF_STATE;
tvstruct.item.stateMask = TVIS_EXPANDEDONCE;
tvstruct.item.state = TVIS_EXPANDEDONCE;
tvstruct.item.cChildren = 0;
SetItem(&tvstruct.item);
EnsureVisible (hParent); // 10-26-96 force parent to update
}
hItem = 0;
}
// ***************************************************************************
//
// CClassTree::OnScroll
//
// Description:
// Scroll the window by a line only. Called only by the drop target
// when it detects that a drag operation is in the scrolling region.
//
// Parameters:
// UINT nScrollCode Scrolling request.
// UINT nPos Not used.
// BOOL bDoScroll If TRUE do the scroll; otherwise just
// return whither or not a scroll could occur.
//
// Returns:
// BOOL TRUE if could scroll; otherwise FALSE.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
BOOL CClassTree::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll)
{
// Read the docs on CView::OnScroll to understand the semantics of
// bDoScroll.
// calc new x position
int x = GetScrollPos(SB_HORZ);
switch (LOBYTE(nScrollCode))
{
case SB_LINEUP:
x = -1;
break;
case SB_LINEDOWN:
x = 1;
break;
}
// calc new y position
int y = GetScrollPos(SB_VERT);
switch (HIBYTE(nScrollCode))
{
case SB_LINEUP:
y = -1;
break;
case SB_LINEDOWN:
y = 1;
break;
}
BOOL bResult = OnScrollBy(CSize(x, y ), bDoScroll);
return bResult;
}
//***************************************************************************
//
// CClassTree::OnScrollBy
//
// Purpose:
//
// This is work in progress.
//
//***************************************************************************
// ***************************************************************************
//
// CClassTree::OnScrollBy
//
// Description:
// Actually scrolls the window if bDoScroll it TRUE. If bDSoScroll
// is FALSE test to see if a scroll could be done.
//
// Parameters:
// CSize sizeScroll Number of pixels scrolled horizontally
// and vertically.
// BOOL bDoScroll If TRUE do the scroll; otherwise just
// return whither or not a scroll could occur.
//
// Returns:
// BOOL TRUE if could scroll; otherwise FALSE.
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
BOOL CClassTree::OnScrollBy(CSize sizeScroll, BOOL bDoScroll)
{
int nScrollH = sizeScroll.cx;
int nScrollV = sizeScroll.cy;
int xOrig;
int yOrig;
int x = sizeScroll.cx;
int y = sizeScroll.cy;
CRect rControl;
GetClientRect(&rControl);
CDC *pdc = GetDC( );
pdc -> LPtoDP(&rControl);
ClientToScreen(&rControl);
ReleaseDC(pdc);
SCROLLINFO siHInfo;
SCROLLINFO siVInfo;
siHInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
siVInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
BOOL bReturn;
bReturn = GetScrollInfo(SB_HORZ, &siHInfo, SIF_ALL);
bReturn = GetScrollInfo(SB_VERT, &siVInfo ,SIF_ALL);
long lStyle = GetWindowLong(GetSafeHwnd(), GWL_STYLE);
BOOL bHScroll = lStyle & WS_HSCROLL;
BOOL bVScroll = lStyle & WS_VSCROLL;
// don't scroll if there is no valid scroll range (ie. no scroll bar)
if (!bVScroll)
{
// vertical scroll bar not enabled
sizeScroll.cy = 0;
}
if (!bHScroll)
{
// horizontal scroll bar not enabled
sizeScroll.cx = 0;
}
// adjust current x position
xOrig = GetScrollPos(SB_HORZ);
int xMax = GetScrollLimit(SB_HORZ);
x += xOrig;
if (x < 0)
x = 0;
else if (x > xMax)
x = xMax;
// adjust current y position
yOrig = GetScrollPos(SB_VERT);
int yMax = GetScrollLimit(SB_VERT);
y += yOrig;
if (y < 0)
y = 0;
else if (y > yMax)
y = yMax;
//did anything change?
if (x == xOrig && y == yOrig)
return FALSE;
if (bDoScroll)
{
bReturn;
WPARAM wParam;
LPARAM lParam;
wParam = MAKEWPARAM((nScrollV < 0) ? SB_LINEUP : SB_LINEDOWN, yOrig);
lParam = NULL;
this -> SendMessage(WM_VSCROLL, wParam, lParam);
wParam = MAKEWPARAM((nScrollH < 0) ? SB_LINEUP : SB_LINEDOWN, xOrig);
lParam = NULL;
this -> SendMessage(WM_HSCROLL, wParam, lParam);
bReturn = ::UpdateWindow(GetSafeHwnd());
bReturn = GetScrollInfo(SB_VERT, &siVInfo ,SIF_ALL);
m_pParent -> InvalidateControl();
m_pParent -> SetModifiedFlag( TRUE );
}
return TRUE;
}
// ***************************************************************************
//
// CClassTree::ReleaseClassObjects
//
// Description:
// Release (in OLE sense) the IWbemClassobject instances.
//
// Parameters:
// HTREEITEM hItem Tree root to start releasing from.
//
// Returns:
// VOID
//
// Globals accessed:
// NONE
//
// Globals modified:
// NONE
//
// ***************************************************************************
void CClassTree::ReleaseClassObjects(HTREEITEM hItem)
{
IWbemClassObject *pClassObject
= reinterpret_cast<IWbemClassObject *>(GetItemData( hItem ));
if (pClassObject)
{
pClassObject -> Release();
SetItemData(hItem,NULL);
}
if (!ItemHasChildren (hItem))
{
return;
}
HTREEITEM hChild = GetChildItem(hItem);
while (hChild)
{
ReleaseClassObjects(hChild);
hChild = GetNextSiblingItem(hChild);
}
}
LRESULT CClassTree::SelectTreeItemOnFocus(WPARAM, LPARAM)
{
if (m_nSpinFocus < 1)
{
m_nSpinFocus++;
HTREEITEM hItem = GetSelectedItem();
if (hItem)
{
m_nSelectedItem = hItem;
}
PostMessage(SELECTITEMONFOCUS,0,0);
return 0;
}
HTREEITEM hSelectedItem = GetSelectedItem();
if (hSelectedItem && m_nSelectedItem && GetCount() != -1)
{
SelectItem(m_nSelectedItem);
SetFocus();
IWbemClassObject *pItem = (IWbemClassObject*)GetItemData(m_nSelectedItem);
if (pItem)
{
if (m_pParent->m_bReadySignal)
{
COleVariant covClass;
CString csItem = GetIWbemFullPath(m_pParent->GetServices(),pItem);
covClass = csItem;
m_pParent -> FireEditExistingClass(covClass);
#ifdef _DEBUG
afxDump <<"CClassTree::SelectTreeItemOnFocus: m_pParent -> FireEditExistingClass(covClass); \n";
afxDump << " " << csItem << "\n";
#endif
}
}
}
m_pParent->InvalidateControl();
m_pParent -> PostMessage(SETFOCUSTREE,0,0);
return 0;
}
LRESULT CClassTree::SelectTreeItem(WPARAM, LPARAM)
{
m_bMouseDown = FALSE;
m_bKeyDown = FALSE;
m_bUseItem = FALSE;
m_hItemToUse = NULL;
if (m_uiTimer)
{
KillTimer( m_uiTimer );
m_uiTimer = 0;
}
HTREEITEM hItem = GetSelectedItem();
if (!hItem)
{
return 0;
}
m_bUseItem = TRUE;
m_hItemToUse = hItem;
CPoint point(0,0);
ContinueProcessSelection(0, point);
return 0;
}
void CClassTree::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;
switch (pTVKeyDown->wVKey)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_NEXT:
case VK_PRIOR:
case VK_HOME:
case VK_END:
if (m_uiTimer)
{
KillTimer( m_uiTimer );
m_uiTimer = 0;
}
m_uiTimer = (UINT) SetTimer(KBSelectionTimer, 250, SelectItemAfterDelay);
m_bKeyDown = TRUE;
m_bMouseDown = FALSE;
break;
default:
m_bKeyDown = FALSE;
m_bMouseDown = TRUE;
break;
};
// TODO: Add your control notification handler code here
*pResult = 0;
}
void CClassTree::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
#ifdef _DEBUG
afxDump << _T("CClassTree::OnKillfocus\n");
#endif
m_pParent->m_bRestoreFocusToTree = TRUE;
*pResult = 0;
}
void CClassTree::OnSetfocus(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
#ifdef _DEBUG
afxDump << _T("Before COleControl::OnActivateInPlace in CClassTree::OnSetFocus\n");
#endif
// TODO: Add your message handler code here
m_pParent->OnActivateInPlace(TRUE,NULL);
#ifdef _DEBUG
afxDump << _T("After COleControl::OnActivateInPlace in CClassTree::OnSetFocus\n");
#endif
m_pParent->m_bRestoreFocusToTree = TRUE;
*pResult = 0;
}
void CClassTree::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
m_pParent -> OnActivateInPlace(TRUE,NULL);
HTREEITEM hOld = pNMTreeView->itemOld.hItem;
CString csSelection = GetSelectionPath(hOld);
BOOL bCanChangeSelection = m_pParent->QueryCanChangeSelection(csSelection);
if (!bCanChangeSelection)
{
SetFocus();
*pResult = TRUE;
return;
}
*pResult = 0;
UINT uInterval = GetDoubleClickTime();
if (uInterval > 0)
{
if (m_uiSelectionTimer)
{
KillTimer( m_uiSelectionTimer );
m_uiSelectionTimer = 0;
}
gpTreeTmp = this;
m_lSelection = 1;
m_uiSelectionTimer =(UINT) ::SetTimer
(this->m_hWnd,
ExpansionOrSelectionTimer,
/*uInterval + */50,
ExpansionOrSelection);
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hItem = pnmtv->itemNew.hItem;
m_bUseItem = TRUE;
m_hItemToUse = hItem;
}
*pResult = 0;
}
/* EOF: CClassTree.cpp */