mirror of
https://github.com/reactos/reactos.git
synced 2024-08-05 19:11:16 +00:00
[DEVMGR]
- Implement dynamic context menu for device and class nodes - Fix CanUninstall to return correct results - Strings hardcoded for now, will fix soon svn path=/trunk/; revision=68334
This commit is contained in:
parent
5c8a9ffd29
commit
27e12f2db6
|
@ -16,7 +16,7 @@ CClassNode::CClassNode(
|
||||||
_In_ LPGUID ClassGuid,
|
_In_ LPGUID ClassGuid,
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
) :
|
) :
|
||||||
CNode(ImageListData)
|
CNode(ClassNode, ImageListData)
|
||||||
{
|
{
|
||||||
CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
|
CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ CDeviceNode::CDeviceNode(
|
||||||
_In_opt_ DEVINST Device,
|
_In_opt_ DEVINST Device,
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
) :
|
) :
|
||||||
CNode(ImageListData),
|
CNode(DeviceNode, ImageListData),
|
||||||
m_DevInst(Device),
|
m_DevInst(Device),
|
||||||
m_hDevInfo(NULL),
|
m_hDevInfo(NULL),
|
||||||
m_Status(0),
|
m_Status(0),
|
||||||
|
@ -260,11 +260,12 @@ CDeviceNode::CanUninstall()
|
||||||
NULL);
|
NULL);
|
||||||
if (cr == CR_SUCCESS)
|
if (cr == CR_SUCCESS)
|
||||||
{
|
{
|
||||||
return ((m_Status & DN_DISABLEABLE) != 0 &&
|
if ((m_Status & DN_ROOT_ENUMERATED) != 0 &&
|
||||||
(m_Status & DN_ROOT_ENUMERATED) == 0);
|
(m_Status & DN_DISABLEABLE) == 0)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -27,10 +27,11 @@ public:
|
||||||
bool HasProblem();
|
bool HasProblem();
|
||||||
bool IsHidden();
|
bool IsHidden();
|
||||||
bool CanDisable();
|
bool CanDisable();
|
||||||
bool IsDisabled();
|
virtual bool IsDisabled();
|
||||||
bool IsStarted();
|
bool IsStarted();
|
||||||
bool IsInstalled();
|
bool IsInstalled();
|
||||||
bool CanUninstall();
|
bool CanUninstall();
|
||||||
|
virtual bool CanUpdate() { return true; } // unimplemented
|
||||||
|
|
||||||
bool EnableDevice(
|
bool EnableDevice(
|
||||||
_In_ bool Enable,
|
_In_ bool Enable,
|
||||||
|
|
|
@ -49,7 +49,6 @@ CDeviceView::CDeviceView(
|
||||||
m_hTreeView(NULL),
|
m_hTreeView(NULL),
|
||||||
m_hPropertyDialog(NULL),
|
m_hPropertyDialog(NULL),
|
||||||
m_hMenu(NULL),
|
m_hMenu(NULL),
|
||||||
m_hContextMenu(NULL),
|
|
||||||
m_ViewType(DevicesByType),
|
m_ViewType(DevicesByType),
|
||||||
m_ShowHidden(FALSE),
|
m_ShowHidden(FALSE),
|
||||||
m_RootClassImage(-1),
|
m_RootClassImage(-1),
|
||||||
|
@ -92,9 +91,7 @@ CDeviceView::Initialize()
|
||||||
SetWindowTheme(m_hTreeView, L"explorer", NULL);
|
SetWindowTheme(m_hTreeView, L"explorer", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the context menu and make properties the default item
|
|
||||||
m_hContextMenu = CreatePopupMenu();
|
|
||||||
SetMenuDefaultItem(m_hContextMenu, IDC_PROPERTIES, FALSE);
|
|
||||||
|
|
||||||
return !!(m_hTreeView);
|
return !!(m_hTreeView);
|
||||||
}
|
}
|
||||||
|
@ -110,8 +107,6 @@ CDeviceView::Uninitialize()
|
||||||
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyMenu(m_hContextMenu);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,26 +163,14 @@ CDeviceView::OnContextMenu(
|
||||||
PtInRect(&rc, pt))
|
PtInRect(&rc, pt))
|
||||||
{
|
{
|
||||||
|
|
||||||
CNode *Node = GetSelectedNode();
|
|
||||||
if (Node && Node->HasProperties())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INT xPos = GET_X_LPARAM(lParam);
|
INT xPos = GET_X_LPARAM(lParam);
|
||||||
INT yPos = GET_Y_LPARAM(lParam);
|
INT yPos = GET_Y_LPARAM(lParam);
|
||||||
|
|
||||||
TrackPopupMenuEx(m_hContextMenu,
|
CNode *Node = GetSelectedNode();
|
||||||
TPM_RIGHTBUTTON,
|
if (Node)
|
||||||
xPos,
|
{
|
||||||
yPos,
|
BuildContextMenuForNode(Node, xPos, yPos);
|
||||||
m_hMainWnd,
|
}
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,6 +790,100 @@ CDeviceView::InsertIntoTreeView(
|
||||||
return TreeView_InsertItem(m_hTreeView, &tvins);
|
return TreeView_InsertItem(m_hTreeView, &tvins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDeviceView::BuildContextMenuForNode(
|
||||||
|
_In_ CNode *Node,
|
||||||
|
_In_ INT xPos,
|
||||||
|
_In_ INT yPos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Create the context menu
|
||||||
|
HMENU hContextMenu = CreatePopupMenu();
|
||||||
|
|
||||||
|
// Create a seperator structure
|
||||||
|
MENUITEMINFOW MenuSeperator = { 0 };
|
||||||
|
MenuSeperator.cbSize = sizeof(MENUITEMINFOW);
|
||||||
|
MenuSeperator.fType = MFT_SEPARATOR;
|
||||||
|
|
||||||
|
// Setup the
|
||||||
|
MENUITEMINFOW MenuItemInfo = { 0 };
|
||||||
|
MenuItemInfo.cbSize = sizeof(MENUITEMINFOW);
|
||||||
|
MenuItemInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_SUBMENU;
|
||||||
|
MenuItemInfo.fType = MFT_STRING;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// Device nodes have extra data
|
||||||
|
if (Node->GetNodeType() == DeviceNode)
|
||||||
|
{
|
||||||
|
CDeviceNode *DeviceNode = dynamic_cast<CDeviceNode *>(Node);
|
||||||
|
|
||||||
|
if (DeviceNode->CanUpdate())
|
||||||
|
{
|
||||||
|
MenuItemInfo.wID = IDC_UPDATE_DRV;
|
||||||
|
MenuItemInfo.dwTypeData = L"Update driver software...";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceNode->IsDisabled())
|
||||||
|
{
|
||||||
|
MenuItemInfo.wID = IDC_ENABLE_DRV;
|
||||||
|
MenuItemInfo.dwTypeData = L"Enable";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceNode->CanDisable() && !DeviceNode->IsDisabled())
|
||||||
|
{
|
||||||
|
MenuItemInfo.wID = IDC_DISABLE_DRV;
|
||||||
|
MenuItemInfo.dwTypeData = L"Disable";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceNode->CanUninstall())
|
||||||
|
{
|
||||||
|
MenuItemInfo.wID = IDC_UNINSTALL_DRV;
|
||||||
|
MenuItemInfo.dwTypeData = L"Uninstall";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All nodes have the scan option
|
||||||
|
MenuItemInfo.wID = IDC_SCAN_HARDWARE;
|
||||||
|
MenuItemInfo.dwTypeData = L"Scan for hardware changes";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (Node->HasProperties())
|
||||||
|
{
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
MenuItemInfo.wID = IDC_PROPERTIES;
|
||||||
|
MenuItemInfo.dwTypeData = L"Properties";
|
||||||
|
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
SetMenuDefaultItem(hContextMenu, IDC_PROPERTIES, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the menu
|
||||||
|
TrackPopupMenuEx(hContextMenu,
|
||||||
|
TPM_RIGHTBUTTON,
|
||||||
|
xPos,
|
||||||
|
yPos,
|
||||||
|
m_hMainWnd,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
DestroyMenu(hContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
HTREEITEM
|
HTREEITEM
|
||||||
CDeviceView::RecurseFindDevice(
|
CDeviceView::RecurseFindDevice(
|
||||||
_In_ HTREEITEM hParentItem,
|
_In_ HTREEITEM hParentItem,
|
||||||
|
@ -828,6 +905,7 @@ CDeviceView::RecurseFindDevice(
|
||||||
if (TreeView_GetItem(m_hTreeView, &tvItem) &&
|
if (TreeView_GetItem(m_hTreeView, &tvItem) &&
|
||||||
tvItem.lParam != NULL)
|
tvItem.lParam != NULL)
|
||||||
{
|
{
|
||||||
|
// check for a matching deviceid
|
||||||
Node = reinterpret_cast<CNode *>(tvItem.lParam);
|
Node = reinterpret_cast<CNode *>(tvItem.lParam);
|
||||||
if (Node->GetDeviceId() &&
|
if (Node->GetDeviceId() &&
|
||||||
(wcscmp(Node->GetDeviceId(), DeviceId) == 0))
|
(wcscmp(Node->GetDeviceId(), DeviceId) == 0))
|
||||||
|
@ -840,7 +918,7 @@ CDeviceView::RecurseFindDevice(
|
||||||
FoundItem = RecurseFindDevice(hItem, DeviceId);
|
FoundItem = RecurseFindDevice(hItem, DeviceId);
|
||||||
if (FoundItem) return FoundItem;
|
if (FoundItem) return FoundItem;
|
||||||
|
|
||||||
// Delete all the siblings
|
// Loop all the siblings
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Get the next item at this level
|
// Get the next item at this level
|
||||||
|
@ -852,6 +930,7 @@ CDeviceView::RecurseFindDevice(
|
||||||
tvItem.mask = TVIF_PARAM;
|
tvItem.mask = TVIF_PARAM;
|
||||||
if (TreeView_GetItem(m_hTreeView, &tvItem))
|
if (TreeView_GetItem(m_hTreeView, &tvItem))
|
||||||
{
|
{
|
||||||
|
// check for a matching deviceid
|
||||||
Node = reinterpret_cast<CNode *>(tvItem.lParam);
|
Node = reinterpret_cast<CNode *>(tvItem.lParam);
|
||||||
if (Node->GetDeviceId() &&
|
if (Node->GetDeviceId() &&
|
||||||
wcscmp(Node->GetDeviceId(), DeviceId) == 0)
|
wcscmp(Node->GetDeviceId(), DeviceId) == 0)
|
||||||
|
@ -879,14 +958,19 @@ CDeviceView::SelectNode(
|
||||||
hRoot = TreeView_GetRoot(m_hTreeView);
|
hRoot = TreeView_GetRoot(m_hTreeView);
|
||||||
if (hRoot == NULL) return;
|
if (hRoot == NULL) return;
|
||||||
|
|
||||||
if (DeviceId)
|
// If we don't want to set select a node, just select root
|
||||||
|
if (DeviceId == NULL)
|
||||||
{
|
{
|
||||||
hItem = RecurseFindDevice(hRoot, DeviceId);
|
TreeView_SelectItem(m_hTreeView, hRoot);
|
||||||
if (hItem)
|
return;
|
||||||
{
|
}
|
||||||
TreeView_SelectItem(m_hTreeView, hItem);
|
|
||||||
TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND);
|
// Scan the tree looking for the node we want
|
||||||
}
|
hItem = RecurseFindDevice(hRoot, DeviceId);
|
||||||
|
if (hItem)
|
||||||
|
{
|
||||||
|
TreeView_SelectItem(m_hTreeView, hItem);
|
||||||
|
TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,6 @@ class CDeviceView
|
||||||
HWND m_hTreeView;
|
HWND m_hTreeView;
|
||||||
HWND m_hPropertyDialog;
|
HWND m_hPropertyDialog;
|
||||||
HMENU m_hMenu;
|
HMENU m_hMenu;
|
||||||
HMENU m_hContextMenu;
|
|
||||||
ViewType m_ViewType;
|
ViewType m_ViewType;
|
||||||
HTREEITEM m_hTreeRoot;
|
HTREEITEM m_hTreeRoot;
|
||||||
DEVINST m_RootDevInst;
|
DEVINST m_RootDevInst;
|
||||||
|
@ -128,6 +127,12 @@ private:
|
||||||
_In_ CNode *Node
|
_In_ CNode *Node
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void BuildContextMenuForNode(
|
||||||
|
_In_ CNode *Node,
|
||||||
|
_In_ INT xPos,
|
||||||
|
_In_ INT yPos
|
||||||
|
);
|
||||||
|
|
||||||
HTREEITEM RecurseFindDevice(
|
HTREEITEM RecurseFindDevice(
|
||||||
_In_ HTREEITEM hParentItem,
|
_In_ HTREEITEM hParentItem,
|
||||||
_In_ LPWSTR DeviceId
|
_In_ LPWSTR DeviceId
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
/* PUBLIC METHODS *******************************************/
|
/* PUBLIC METHODS *******************************************/
|
||||||
|
|
||||||
CNode::CNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
CNode::CNode(_In_ NodeType Type,
|
||||||
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
|
||||||
|
m_NodeType(Type),
|
||||||
m_ImageListData(ImageListData),
|
m_ImageListData(ImageListData),
|
||||||
m_DeviceId(NULL),
|
m_DeviceId(NULL),
|
||||||
m_ClassImage(0)
|
m_ClassImage(0)
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
|
|
||||||
#define DISPLAY_NAME_LEN 256
|
#define DISPLAY_NAME_LEN 256
|
||||||
|
|
||||||
|
enum NodeType
|
||||||
|
{
|
||||||
|
RootNode,
|
||||||
|
ClassNode,
|
||||||
|
DeviceNode
|
||||||
|
};
|
||||||
|
|
||||||
class CNode
|
class CNode
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -10,9 +17,11 @@ protected:
|
||||||
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
||||||
GUID m_ClassGuid;
|
GUID m_ClassGuid;
|
||||||
INT m_ClassImage;
|
INT m_ClassImage;
|
||||||
|
NodeType m_NodeType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CNode(
|
CNode(
|
||||||
|
_In_ NodeType Type,
|
||||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -20,6 +29,7 @@ public:
|
||||||
|
|
||||||
virtual bool SetupNode() = 0;
|
virtual bool SetupNode() = 0;
|
||||||
|
|
||||||
|
NodeType GetNodeType() { return m_NodeType; }
|
||||||
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
||||||
LPWSTR GetDisplayName() { return m_DisplayName; }
|
LPWSTR GetDisplayName() { return m_DisplayName; }
|
||||||
INT GetClassImage() { return m_ClassImage; }
|
INT GetClassImage() { return m_ClassImage; }
|
||||||
|
|
Loading…
Reference in a new issue