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_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
) :
|
||||
CNode(ImageListData)
|
||||
CNode(ClassNode, ImageListData)
|
||||
{
|
||||
CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ CDeviceNode::CDeviceNode(
|
|||
_In_opt_ DEVINST Device,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
) :
|
||||
CNode(ImageListData),
|
||||
CNode(DeviceNode, ImageListData),
|
||||
m_DevInst(Device),
|
||||
m_hDevInfo(NULL),
|
||||
m_Status(0),
|
||||
|
@ -260,11 +260,12 @@ CDeviceNode::CanUninstall()
|
|||
NULL);
|
||||
if (cr == CR_SUCCESS)
|
||||
{
|
||||
return ((m_Status & DN_DISABLEABLE) != 0 &&
|
||||
(m_Status & DN_ROOT_ENUMERATED) == 0);
|
||||
if ((m_Status & DN_ROOT_ENUMERATED) != 0 &&
|
||||
(m_Status & DN_DISABLEABLE) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -27,10 +27,11 @@ public:
|
|||
bool HasProblem();
|
||||
bool IsHidden();
|
||||
bool CanDisable();
|
||||
bool IsDisabled();
|
||||
virtual bool IsDisabled();
|
||||
bool IsStarted();
|
||||
bool IsInstalled();
|
||||
bool CanUninstall();
|
||||
virtual bool CanUpdate() { return true; } // unimplemented
|
||||
|
||||
bool EnableDevice(
|
||||
_In_ bool Enable,
|
||||
|
|
|
@ -49,7 +49,6 @@ CDeviceView::CDeviceView(
|
|||
m_hTreeView(NULL),
|
||||
m_hPropertyDialog(NULL),
|
||||
m_hMenu(NULL),
|
||||
m_hContextMenu(NULL),
|
||||
m_ViewType(DevicesByType),
|
||||
m_ShowHidden(FALSE),
|
||||
m_RootClassImage(-1),
|
||||
|
@ -92,9 +91,7 @@ CDeviceView::Initialize()
|
|||
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);
|
||||
}
|
||||
|
@ -110,8 +107,6 @@ CDeviceView::Uninitialize()
|
|||
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
|
||||
}
|
||||
|
||||
DestroyMenu(m_hContextMenu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -168,26 +163,14 @@ CDeviceView::OnContextMenu(
|
|||
PtInRect(&rc, pt))
|
||||
{
|
||||
|
||||
CNode *Node = GetSelectedNode();
|
||||
if (Node && Node->HasProperties())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
INT xPos = GET_X_LPARAM(lParam);
|
||||
INT yPos = GET_Y_LPARAM(lParam);
|
||||
|
||||
TrackPopupMenuEx(m_hContextMenu,
|
||||
TPM_RIGHTBUTTON,
|
||||
xPos,
|
||||
yPos,
|
||||
m_hMainWnd,
|
||||
NULL);
|
||||
CNode *Node = GetSelectedNode();
|
||||
if (Node)
|
||||
{
|
||||
BuildContextMenuForNode(Node, xPos, yPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,6 +790,100 @@ CDeviceView::InsertIntoTreeView(
|
|||
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
|
||||
CDeviceView::RecurseFindDevice(
|
||||
_In_ HTREEITEM hParentItem,
|
||||
|
@ -828,6 +905,7 @@ 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))
|
||||
|
@ -840,7 +918,7 @@ CDeviceView::RecurseFindDevice(
|
|||
FoundItem = RecurseFindDevice(hItem, DeviceId);
|
||||
if (FoundItem) return FoundItem;
|
||||
|
||||
// Delete all the siblings
|
||||
// Loop all the siblings
|
||||
for (;;)
|
||||
{
|
||||
// Get the next item at this level
|
||||
|
@ -852,6 +930,7 @@ 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)
|
||||
|
@ -879,14 +958,19 @@ CDeviceView::SelectNode(
|
|||
hRoot = TreeView_GetRoot(m_hTreeView);
|
||||
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);
|
||||
if (hItem)
|
||||
{
|
||||
TreeView_SelectItem(m_hTreeView, hItem);
|
||||
TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND);
|
||||
}
|
||||
TreeView_SelectItem(m_hTreeView, hRoot);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
|
|
|
@ -20,7 +20,6 @@ class CDeviceView
|
|||
HWND m_hTreeView;
|
||||
HWND m_hPropertyDialog;
|
||||
HMENU m_hMenu;
|
||||
HMENU m_hContextMenu;
|
||||
ViewType m_ViewType;
|
||||
HTREEITEM m_hTreeRoot;
|
||||
DEVINST m_RootDevInst;
|
||||
|
@ -128,6 +127,12 @@ private:
|
|||
_In_ CNode *Node
|
||||
);
|
||||
|
||||
void BuildContextMenuForNode(
|
||||
_In_ CNode *Node,
|
||||
_In_ INT xPos,
|
||||
_In_ INT yPos
|
||||
);
|
||||
|
||||
HTREEITEM RecurseFindDevice(
|
||||
_In_ HTREEITEM hParentItem,
|
||||
_In_ LPWSTR DeviceId
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
/* 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_DeviceId(NULL),
|
||||
m_ClassImage(0)
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
#define DISPLAY_NAME_LEN 256
|
||||
|
||||
enum NodeType
|
||||
{
|
||||
RootNode,
|
||||
ClassNode,
|
||||
DeviceNode
|
||||
};
|
||||
|
||||
class CNode
|
||||
{
|
||||
protected:
|
||||
|
@ -10,9 +17,11 @@ protected:
|
|||
WCHAR m_DisplayName[DISPLAY_NAME_LEN];
|
||||
GUID m_ClassGuid;
|
||||
INT m_ClassImage;
|
||||
NodeType m_NodeType;
|
||||
|
||||
public:
|
||||
CNode(
|
||||
_In_ NodeType Type,
|
||||
_In_ PSP_CLASSIMAGELIST_DATA ImageListData
|
||||
);
|
||||
|
||||
|
@ -20,6 +29,7 @@ public:
|
|||
|
||||
virtual bool SetupNode() = 0;
|
||||
|
||||
NodeType GetNodeType() { return m_NodeType; }
|
||||
LPGUID GetClassGuid() { return &m_ClassGuid; }
|
||||
LPWSTR GetDisplayName() { return m_DisplayName; }
|
||||
INT GetClassImage() { return m_ClassImage; }
|
||||
|
|
Loading…
Reference in a new issue