- 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
This commit is contained in:
Ged Murphy
2015-10-23 12:45:41 +00:00
parent ba56cef9c1
commit 285e7278f5
6 changed files with 98 additions and 53 deletions
@@ -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.
@@ -20,6 +20,10 @@ public:
~CDeviceNode();
CDeviceNode(
_In_ const CDeviceNode &Node
);
virtual bool SetupNode();
DEVINST GetDeviceInst() { return m_DevInst; }
+56 -49
View File
@@ -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<CClassNode *>(LastSelectedNode));
}
else if (LastSelectedNode->GetNodeType() == DeviceNode)
{
LastSelectedNode = new CDeviceNode(*dynamic_cast<CDeviceNode *>(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<CNode *>(tvItem.lParam);
if (Node->GetDeviceId() &&
(wcscmp(Node->GetDeviceId(), DeviceId) == 0))
// check for a matching node
FoundNode = reinterpret_cast<CNode *>(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<CNode *>(tvItem.lParam);
if (Node->GetDeviceId() &&
wcscmp(Node->GetDeviceId(), DeviceId) == 0)
// check for a matching class
FoundNode = reinterpret_cast<CNode *>(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
@@ -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(
+12 -1
View File
@@ -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()
{
}
}
+4
View File
@@ -25,6 +25,10 @@ public:
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
);
CNode(
_In_ const CNode& Node
);
virtual ~CNode();
virtual bool SetupNode() = 0;