From 285e7278f5e618f02f41affef12c3ab863f46d8e Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Fri, 23 Oct 2015 12:45:41 +0000 Subject: [PATCH] [DEVMGR] - When refreshing the view, reselect and expand the previously selected node in the tree. This allows to switch from 'by type' to 'by connection' and see where the selected device sits in the tree hierarchy (and vice versa) svn path=/trunk/; revision=69658 --- .../dll/win32/devmgr/devmgmt/DeviceNode.cpp | 21 +++- reactos/dll/win32/devmgr/devmgmt/DeviceNode.h | 4 + .../dll/win32/devmgr/devmgmt/DeviceView.cpp | 105 ++++++++++-------- reactos/dll/win32/devmgr/devmgmt/DeviceView.h | 4 +- reactos/dll/win32/devmgr/devmgmt/Node.cpp | 13 ++- reactos/dll/win32/devmgr/devmgmt/Node.h | 4 + 6 files changed, 98 insertions(+), 53 deletions(-) diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp b/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp index 96d6a397d39..eff0d5c5cdf 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceNode.cpp @@ -26,6 +26,24 @@ CDeviceNode::CDeviceNode( ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA)); } +CDeviceNode::CDeviceNode( + _In_ const CDeviceNode &Node + ) : + CNode(Node) +{ + m_DevInst = Node.m_DevInst; + m_hDevInfo = Node.m_hDevInfo; + m_Status = Node.m_Status; + m_ProblemNumber = Node.m_ProblemNumber; + m_OverlayImage = Node.m_OverlayImage; + CopyMemory(&m_DevinfoData, &Node.m_DevinfoData, sizeof(SP_DEVINFO_DATA)); + + size_t size = wcslen(Node.m_DeviceId) + 1; + m_DeviceId = new WCHAR[size]; + StringCbCopyW(m_DeviceId, size * sizeof(WCHAR), Node.m_DeviceId); + +} + CDeviceNode::~CDeviceNode() { Cleanup(); @@ -290,7 +308,7 @@ CDeviceNode::EnableDevice( for (int i = 0; i < 2; i++) { // Check globally first, then check config specific - pcp.Scope = (i == 0) ? DICS_FLAG_GLOBAL : DICS_FLAG_CONFIGSPECIFIC; + pcp.Scope = (i == 0) ? DICS_FLAG_CONFIGGENERAL : DICS_FLAG_CONFIGSPECIFIC; if (SetupDiSetClassInstallParamsW(m_hDevInfo, &m_DevinfoData, @@ -320,6 +338,7 @@ CDeviceNode::EnableDevice( SetupDiChangeState(m_hDevInfo, &m_DevinfoData); } + if (Enable) { // config specific enabling first, then global enabling. diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h b/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h index 3c5ddc5c0c3..58520b616b0 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceNode.h @@ -20,6 +20,10 @@ public: ~CDeviceNode(); + CDeviceNode( + _In_ const CDeviceNode &Node + ); + virtual bool SetupNode(); DEVINST GetDeviceInst() { return m_DevInst; } diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp b/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp index 388a258e30c..13b14d4a286 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp @@ -27,7 +27,6 @@ struct RefreshThreadData CDeviceView *This; BOOL ScanForChanges; BOOL UpdateView; - LPWSTR DeviceId; }; @@ -79,6 +78,10 @@ CDeviceView::Initialize() // Give the treeview arrows instead of +/- boxes (on Win7) SetWindowTheme(m_hTreeView, L"explorer", NULL); + + // Create the root node + m_RootNode = new CRootNode(&m_ImageListData); + m_RootNode->SetupNode(); } @@ -198,15 +201,6 @@ CDeviceView::Refresh( ThreadData->This = this; ThreadData->ScanForChanges = ScanForChanges; ThreadData->UpdateView = UpdateView; - ThreadData->DeviceId = NULL; - - if (DeviceId) - { - // Node gets deleted on refresh so we copy it to another block - size_t Length = wcslen(DeviceId) + 1; - ThreadData->DeviceId = new WCHAR[Length]; - StringCbCopyW(ThreadData->DeviceId, Length, DeviceId); - } HANDLE hThread; @@ -377,13 +371,29 @@ unsigned int __stdcall CDeviceView::RefreshThread(void *Param) RefreshThreadData *ThreadData = (RefreshThreadData *)Param; CDeviceView *This = ThreadData->This; + // Get a copy of the currently selected node + CNode *LastSelectedNode = This->GetSelectedNode(); + if (LastSelectedNode == nullptr || (LastSelectedNode->GetNodeType() == RootNode)) + { + LastSelectedNode = new CRootNode(*This->m_RootNode); + } + else if (LastSelectedNode->GetNodeType() == ClassNode) + { + LastSelectedNode = new CClassNode(*dynamic_cast(LastSelectedNode)); + } + else if (LastSelectedNode->GetNodeType() == DeviceNode) + { + LastSelectedNode = new CDeviceNode(*dynamic_cast(LastSelectedNode)); + } // Empty the treeview This->EmptyDeviceView(); - This->m_hTreeRoot = NULL; - // Refresh the devices only if requested. This means - // switching views uses the cache and remains fast + // Re-add the root node to the tree + if (This->AddRootDevice() == false) + return 0; + + // Refresh the devices only if requested if (ThreadData->ScanForChanges) { This->RefreshDeviceList(); @@ -408,10 +418,8 @@ unsigned int __stdcall CDeviceView::RefreshThread(void *Param) } - This->SelectNode(ThreadData->DeviceId); + This->SelectNode(LastSelectedNode); - if (ThreadData->DeviceId) - delete[] ThreadData->DeviceId; delete ThreadData; return 0; @@ -429,10 +437,6 @@ CDeviceView::ListDevicesByType() INT ClassIndex; BOOL bClassSuccess, bSuccess; - // Start by adding the root node to the tree - bSuccess = AddRootDevice(); - if (bSuccess == false) return false; - ClassIndex = 0; do { @@ -564,12 +568,6 @@ CDeviceView::ListDevicesByType() bool CDeviceView::ListDevicesByConnection() { - bool bSuccess; - - // Start by adding the root node to the tree - bSuccess = AddRootDevice(); - if (bSuccess == false) return false; - // Walk the device tree and add all the devices (void)RecurseChildDevices(m_RootNode->GetDeviceInst(), m_hTreeRoot); @@ -928,13 +926,13 @@ CDeviceView::BuildActionMenuForNode( HTREEITEM CDeviceView::RecurseFindDevice( _In_ HTREEITEM hParentItem, - _In_ LPWSTR DeviceId + _In_ CNode *Node ) { HTREEITEM FoundItem; HTREEITEM hItem; TVITEMW tvItem; - CNode *Node; + CNode *FoundNode; // Check if this node has any children hItem = TreeView_GetChild(m_hTreeView, hParentItem); @@ -946,17 +944,22 @@ CDeviceView::RecurseFindDevice( if (TreeView_GetItem(m_hTreeView, &tvItem) && tvItem.lParam != NULL) { - // check for a matching deviceid - Node = reinterpret_cast(tvItem.lParam); - if (Node->GetDeviceId() && - (wcscmp(Node->GetDeviceId(), DeviceId) == 0)) + // check for a matching node + FoundNode = reinterpret_cast(tvItem.lParam); + if ((FoundNode->GetNodeType() == Node->GetNodeType()) && + (IsEqualGUID(*FoundNode->GetClassGuid(), *Node->GetClassGuid()))) { - return hItem; + // check if this is a class node, or a device with matching ID's + if ((FoundNode->GetNodeType() == ClassNode) || + (wcscmp(FoundNode->GetDeviceId(), Node->GetDeviceId()) == 0)) + { + return hItem; + } } } // This node may have its own children - FoundItem = RecurseFindDevice(hItem, DeviceId); + FoundItem = RecurseFindDevice(hItem, Node); if (FoundItem) return FoundItem; // Loop all the siblings @@ -971,17 +974,22 @@ CDeviceView::RecurseFindDevice( tvItem.mask = TVIF_PARAM; if (TreeView_GetItem(m_hTreeView, &tvItem)) { - // check for a matching deviceid - Node = reinterpret_cast(tvItem.lParam); - if (Node->GetDeviceId() && - wcscmp(Node->GetDeviceId(), DeviceId) == 0) + // check for a matching class + FoundNode = reinterpret_cast(tvItem.lParam); + if ((FoundNode->GetNodeType() == Node->GetNodeType()) && + (IsEqualGUID(*FoundNode->GetClassGuid(), *Node->GetClassGuid()))) { - return hItem; + // check if this is a class node, or a device with matching ID's + if ((FoundNode->GetNodeType() == ClassNode) || + (wcscmp(FoundNode->GetDeviceId(), Node->GetDeviceId()) == 0)) + { + return hItem; + } } } // This node may have its own children - FoundItem = RecurseFindDevice(hItem, DeviceId); + FoundItem = RecurseFindDevice(hItem, Node); if (FoundItem) return FoundItem; } @@ -990,7 +998,7 @@ CDeviceView::RecurseFindDevice( void CDeviceView::SelectNode( - _In_ LPWSTR DeviceId + _In_ CNode *Node ) { HTREEITEM hRoot, hItem; @@ -1000,18 +1008,17 @@ CDeviceView::SelectNode( if (hRoot == NULL) return; // If we don't want to set select a node, just select root - if (DeviceId == NULL) + if (Node == nullptr || Node->GetNodeType() == RootNode) { TreeView_SelectItem(m_hTreeView, hRoot); return; } // Scan the tree looking for the node we want - hItem = RecurseFindDevice(hRoot, DeviceId); + hItem = RecurseFindDevice(hRoot, Node); if (hItem) { TreeView_SelectItem(m_hTreeView, hItem); - TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND); } else { @@ -1033,7 +1040,7 @@ CDeviceView::GetClassNode( ) { POSITION Pos; - CClassNode *Node; + CClassNode *Node = nullptr; Pos = m_ClassNodeList.GetHeadPosition(); if (Pos == NULL) return nullptr; @@ -1047,7 +1054,7 @@ CDeviceView::GetClassNode( break; } - Node = NULL; + Node = nullptr; } while (Pos != NULL); @@ -1060,7 +1067,7 @@ CDeviceView::GetDeviceNode( ) { POSITION Pos; - CDeviceNode *Node; + CDeviceNode *Node = nullptr; Pos = m_DeviceNodeList.GetHeadPosition(); if (Pos == NULL) return nullptr; @@ -1074,7 +1081,7 @@ CDeviceView::GetDeviceNode( break; } - Node = NULL; + Node = nullptr; } while (Pos != NULL); @@ -1090,7 +1097,7 @@ CNode* CDeviceView::GetNode( { return (CNode *)TvItem->lParam; } - return NULL; + return nullptr; } void diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.h b/reactos/dll/win32/devmgr/devmgmt/DeviceView.h index 24973f05b75..eb0383e90fb 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceView.h +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceView.h @@ -148,11 +148,11 @@ private: HTREEITEM RecurseFindDevice( _In_ HTREEITEM hParentItem, - _In_ LPWSTR DeviceId + _In_ CNode *Node ); void SelectNode( - _In_ LPWSTR DeviceId + _In_ CNode *Node ); void EmptyDeviceView( diff --git a/reactos/dll/win32/devmgr/devmgmt/Node.cpp b/reactos/dll/win32/devmgr/devmgmt/Node.cpp index 1925d2db756..6e7d761894a 100644 --- a/reactos/dll/win32/devmgr/devmgmt/Node.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/Node.cpp @@ -25,6 +25,17 @@ CNode::CNode(_In_ NodeType Type, m_ClassGuid = GUID_NULL; } +CNode::CNode(const CNode &Node) +{ + m_NodeType = Node.m_NodeType; + m_ImageListData = Node.m_ImageListData; + m_DeviceId = Node.m_DeviceId; + m_ClassImage = Node.m_ClassImage; + + StringCbCopyW(m_DisplayName, DISPLAY_NAME_LEN, Node.m_DisplayName); + CopyMemory(&m_ClassGuid, &Node.m_ClassGuid, sizeof(GUID)); +} + CNode::~CNode() { -} +} \ No newline at end of file diff --git a/reactos/dll/win32/devmgr/devmgmt/Node.h b/reactos/dll/win32/devmgr/devmgmt/Node.h index 373d27bea97..c511112b8a5 100644 --- a/reactos/dll/win32/devmgr/devmgmt/Node.h +++ b/reactos/dll/win32/devmgr/devmgmt/Node.h @@ -25,6 +25,10 @@ public: _In_ PSP_CLASSIMAGELIST_DATA ImageListData ); + CNode( + _In_ const CNode& Node + ); + virtual ~CNode(); virtual bool SetupNode() = 0;