- Add a separate class for the root node
- Move creating the action menu items to a generic function so we can use it for both the context menu and the main menu
- Create the main action menu as a dynamic popup menu. It doesn't work quite the same as the menus via the resources, so if any menu expects know how to fix this, be my guest

svn path=/trunk/; revision=68342
This commit is contained in:
Ged Murphy 2015-07-04 21:12:06 +00:00
parent f871bb9384
commit b5e1b529b3
9 changed files with 174 additions and 104 deletions

View file

@ -51,8 +51,7 @@ CDeviceView::CDeviceView(
m_hMenu(NULL), m_hMenu(NULL),
m_ViewType(DevicesByType), m_ViewType(DevicesByType),
m_ShowHidden(FALSE), m_ShowHidden(FALSE),
m_RootClassImage(-1), m_RootNode(NULL)
m_RootDevInst(0)
{ {
ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA)); ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
} }
@ -162,14 +161,27 @@ CDeviceView::OnContextMenu(
ScreenToClient(m_hTreeView, &pt) && ScreenToClient(m_hTreeView, &pt) &&
PtInRect(&rc, pt)) PtInRect(&rc, pt))
{ {
INT xPos = GET_X_LPARAM(lParam);
INT yPos = GET_Y_LPARAM(lParam);
CNode *Node = GetSelectedNode(); CNode *Node = GetSelectedNode();
if (Node) if (Node)
{ {
BuildContextMenuForNode(Node, xPos, yPos); // Create the context menu
HMENU hContextMenu = CreatePopupMenu();
// Add the actions for this node
BuildActionMenuForNode(hContextMenu, Node);
INT xPos = GET_X_LPARAM(lParam);
INT yPos = GET_Y_LPARAM(lParam);
// Display the menu
TrackPopupMenuEx(hContextMenu,
TPM_RIGHTBUTTON,
xPos,
yPos,
m_hMainWnd,
NULL);
DestroyMenu(hContextMenu);
} }
} }
} }
@ -258,6 +270,22 @@ CDeviceView::SetFocus()
{ {
} }
bool
CDeviceView::CreateActionMenu(
_In_ HMENU OwnerMenu,
_In_ bool MainMenu
)
{
CNode *Node = GetSelectedNode();
if (Node)
{
BuildActionMenuForNode(OwnerMenu, Node);
return true;
}
return false;
}
bool bool
CDeviceView::HasProperties( CDeviceView::HasProperties(
_In_ LPTV_ITEMW TvItem _In_ LPTV_ITEMW TvItem
@ -336,54 +364,8 @@ CDeviceView::EnableSelectedDevice(
bool bool
CDeviceView::AddRootDevice() CDeviceView::AddRootDevice()
{ {
// Check whether we've loaded the root bitmap into the imagelist (done on first run) m_hTreeRoot = InsertIntoTreeView(NULL, m_RootNode);
if (m_RootClassImage == -1)
{
// Load the bitmap we'll be using as the root image
HBITMAP hRootImage;
hRootImage = LoadBitmapW(g_hInstance,
MAKEINTRESOURCEW(IDB_ROOT_IMAGE));
if (hRootImage == NULL) return FALSE;
// Add this bitmap to the device image list. This is a bit hacky, but it's safe
m_RootClassImage = ImageList_Add(m_ImageListData.ImageList,
hRootImage,
NULL);
DeleteObject(hRootImage);
}
// Get the root instance
CONFIGRET cr;
cr = CM_Locate_DevNodeW(&m_RootDevInst,
NULL,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
{
return false;
}
// The root name is the computer name
WCHAR RootDeviceName[ROOT_NAME_SIZE];
DWORD Size = ROOT_NAME_SIZE;
if (GetComputerNameW(RootDeviceName, &Size))
_wcslwr_s(RootDeviceName);
TV_ITEMW tvi;
TV_INSERTSTRUCT tvins;
ZeroMemory(&tvi, sizeof(tvi));
ZeroMemory(&tvins, sizeof(tvins));
// Insert the root / parent item into our treeview
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.pszText = RootDeviceName;
tvi.cchTextMax = wcslen(RootDeviceName);
tvi.iImage = m_RootClassImage;
tvi.iSelectedImage = m_RootClassImage;
tvins.item = tvi;
m_hTreeRoot = TreeView_InsertItem(m_hTreeView, &tvins);
return (m_hTreeRoot != NULL); return (m_hTreeRoot != NULL);
} }
bool bool
@ -622,7 +604,7 @@ CDeviceView::ListDevicesByConnection()
if (bSuccess == false) return false; if (bSuccess == false) return false;
// Walk the device tree and add all the devices // Walk the device tree and add all the devices
(void)RecurseChildDevices(m_RootDevInst, m_hTreeRoot); (void)RecurseChildDevices(m_RootNode->GetDeviceInst(), m_hTreeRoot);
// Expand the root item // Expand the root item
(void)TreeView_Expand(m_hTreeView, (void)TreeView_Expand(m_hTreeView,
@ -755,11 +737,10 @@ CDeviceView::GetSiblingDevice(
HTREEITEM HTREEITEM
CDeviceView::InsertIntoTreeView( CDeviceView::InsertIntoTreeView(
_In_ HTREEITEM hParent, _In_opt_ HTREEITEM hParent,
_In_ CNode *Node _In_ CNode *Node
) )
{ {
LPWSTR lpLabel; LPWSTR lpLabel;
lpLabel = Node->GetDisplayName(); lpLabel = Node->GetDisplayName();
@ -791,15 +772,11 @@ CDeviceView::InsertIntoTreeView(
} }
void void
CDeviceView::BuildContextMenuForNode( CDeviceView::BuildActionMenuForNode(
_In_ CNode *Node, _In_ HMENU OwnerMenu,
_In_ INT xPos, _In_ CNode *Node
_In_ INT yPos
) )
{ {
// Create the context menu
HMENU hContextMenu = CreatePopupMenu();
// Create a seperator structure // Create a seperator structure
MENUITEMINFOW MenuSeperator = { 0 }; MENUITEMINFOW MenuSeperator = { 0 };
MenuSeperator.cbSize = sizeof(MENUITEMINFOW); MenuSeperator.cbSize = sizeof(MENUITEMINFOW);
@ -824,7 +801,7 @@ CDeviceView::BuildContextMenuForNode(
String.LoadStringW(g_hInstance, IDS_MENU_UPDATE); String.LoadStringW(g_hInstance, IDS_MENU_UPDATE);
MenuItemInfo.wID = IDC_UPDATE_DRV; MenuItemInfo.wID = IDC_UPDATE_DRV;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
} }
@ -833,7 +810,7 @@ CDeviceView::BuildContextMenuForNode(
String.LoadStringW(g_hInstance, IDS_MENU_ENABLE); String.LoadStringW(g_hInstance, IDS_MENU_ENABLE);
MenuItemInfo.wID = IDC_ENABLE_DRV; MenuItemInfo.wID = IDC_ENABLE_DRV;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
} }
@ -842,7 +819,7 @@ CDeviceView::BuildContextMenuForNode(
String.LoadStringW(g_hInstance, IDS_MENU_DISABLE); String.LoadStringW(g_hInstance, IDS_MENU_DISABLE);
MenuItemInfo.wID = IDC_DISABLE_DRV; MenuItemInfo.wID = IDC_DISABLE_DRV;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
} }
@ -851,11 +828,11 @@ CDeviceView::BuildContextMenuForNode(
String.LoadStringW(g_hInstance, IDS_MENU_UNINSTALL); String.LoadStringW(g_hInstance, IDS_MENU_UNINSTALL);
MenuItemInfo.wID = IDC_UNINSTALL_DRV; MenuItemInfo.wID = IDC_UNINSTALL_DRV;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
} }
InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator);
i++; i++;
} }
@ -863,32 +840,22 @@ CDeviceView::BuildContextMenuForNode(
String.LoadStringW(g_hInstance, IDS_MENU_SCAN); String.LoadStringW(g_hInstance, IDS_MENU_SCAN);
MenuItemInfo.wID = IDC_SCAN_HARDWARE; MenuItemInfo.wID = IDC_SCAN_HARDWARE;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
if (Node->HasProperties()) if (Node->HasProperties())
{ {
InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator);
i++; i++;
String.LoadStringW(g_hInstance, IDS_MENU_PROPERTIES); String.LoadStringW(g_hInstance, IDS_MENU_PROPERTIES);
MenuItemInfo.wID = IDC_PROPERTIES; MenuItemInfo.wID = IDC_PROPERTIES;
MenuItemInfo.dwTypeData = String.GetBuffer(); MenuItemInfo.dwTypeData = String.GetBuffer();
InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
i++; i++;
SetMenuDefaultItem(hContextMenu, IDC_PROPERTIES, FALSE); SetMenuDefaultItem(OwnerMenu, IDC_PROPERTIES, FALSE);
} }
// Display the menu
TrackPopupMenuEx(hContextMenu,
TPM_RIGHTBUTTON,
xPos,
yPos,
m_hMainWnd,
NULL);
DestroyMenu(hContextMenu);
} }
HTREEITEM HTREEITEM
@ -1097,6 +1064,9 @@ CDeviceView::RefreshDeviceList()
EmptyLists(); EmptyLists();
if (m_RootNode) delete m_RootNode;
m_RootNode = new CRootNode(&m_ImageListData);
m_RootNode->SetupNode();
// Loop through all the classes // Loop through all the classes
do do
{ {

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "DeviceNode.h" #include "DeviceNode.h"
#include "ClassNode.h" #include "ClassNode.h"
#include "RootNode.h"
enum ViewType enum ViewType
{ {
@ -13,6 +14,7 @@ enum ViewType
class CDeviceView class CDeviceView
{ {
CRootNode *m_RootNode;
CAtlList<CClassNode *> m_ClassNodeList; CAtlList<CClassNode *> m_ClassNodeList;
CAtlList<CDeviceNode *> m_DeviceNodeList; CAtlList<CDeviceNode *> m_DeviceNodeList;
SP_CLASSIMAGELIST_DATA m_ImageListData; SP_CLASSIMAGELIST_DATA m_ImageListData;
@ -22,9 +24,7 @@ class CDeviceView
HMENU m_hMenu; HMENU m_hMenu;
ViewType m_ViewType; ViewType m_ViewType;
HTREEITEM m_hTreeRoot; HTREEITEM m_hTreeRoot;
DEVINST m_RootDevInst;
bool m_ShowHidden; bool m_ShowHidden;
int m_RootClassImage;
public: public:
CDeviceView( CDeviceView(
@ -68,6 +68,11 @@ public:
ViewType GetCurrentView() { return m_ViewType; } ViewType GetCurrentView() { return m_ViewType; }
bool CreateActionMenu(
_In_ HMENU OwnerMenu,
_In_ bool MainMenu
);
bool HasProperties( bool HasProperties(
_In_ LPTV_ITEMW TvItem _In_ LPTV_ITEMW TvItem
); );
@ -123,14 +128,13 @@ private:
); );
HTREEITEM InsertIntoTreeView( HTREEITEM InsertIntoTreeView(
_In_ HTREEITEM hParent, _In_opt_ HTREEITEM hParent,
_In_ CNode *Node _In_ CNode *Node
); );
void BuildContextMenuForNode( void BuildActionMenuForNode(
_In_ CNode *Node, _In_ HMENU OwnerMenu,
_In_ INT xPos, _In_ CNode *Node
_In_ INT yPos
); );
HTREEITEM RecurseFindDevice( HTREEITEM RecurseFindDevice(

View file

@ -590,6 +590,29 @@ CMainWindow::OnCommand(WPARAM wParam,
break; break;
} }
case IDC_ACTIONMENU:
{
// Create a popup menu with all the actions for the selected node
HMENU hMenu = CreatePopupMenu();
m_DeviceView->CreateActionMenu(hMenu, true);
RECT rc;
GetMenuItemRect(m_hMainWnd, m_hMenu, 1, &rc);
LONG Height = rc.bottom - rc.top;
// Display the menu
TrackPopupMenuEx(hMenu,
TPM_RIGHTBUTTON,
rc.left,
rc.top + Height,
m_hMainWnd,
NULL);
DestroyMenu(hMenu);
break;
}
case IDC_DEVBYTYPE: case IDC_DEVBYTYPE:
{ {
RefreshView(DevicesByType); RefreshView(DevicesByType);

View file

@ -16,6 +16,7 @@ class CMainWindow
HWND m_hToolBar; HWND m_hToolBar;
HIMAGELIST m_ToolbarhImageList; HIMAGELIST m_ToolbarhImageList;
HMENU m_hMenu; HMENU m_hMenu;
HMENU m_hActionMenu;
int m_CmdShow; int m_CmdShow;
public: public:

View file

@ -22,6 +22,7 @@ CNode::CNode(_In_ NodeType Type,
m_ClassImage(0) m_ClassImage(0)
{ {
m_DisplayName[0] = UNICODE_NULL; m_DisplayName[0] = UNICODE_NULL;
m_ClassGuid = GUID_NULL;
} }
CNode::~CNode() CNode::~CNode()

View file

@ -21,8 +21,12 @@
#define IDC_UPDATE_DRV 104 #define IDC_UPDATE_DRV 104
#define IDC_UNINSTALL_DRV 105 #define IDC_UNINSTALL_DRV 105
#define IDC_ADD_HARDWARE 106 #define IDC_ADD_HARDWARE 106
#define IDC_ABOUT 107
#define IDC_EXIT 108 /* Menu items */
#define IDC_ACTIONMENU 150
#define IDC_ABOUT 151
#define IDC_EXIT 152
/* view menu */ /* view menu */
#define IDC_DEVBYTYPE 200 #define IDC_DEVBYTYPE 200

View file

@ -0,0 +1,61 @@
/*
* PROJECT: ReactOS Device Manager
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/devmgr/devmgr/RootNode.cpp
* PURPOSE: Root object for
* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "stdafx.h"
#include "devmgmt.h"
#include "RootNode.h"
CRootNode::CRootNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
CNode(RootNode, ImageListData)
{
}
CRootNode::~CRootNode()
{
}
bool
CRootNode::SetupNode()
{
// Load the bitmap we'll be using as the root image
HBITMAP hRootImage;
hRootImage = LoadBitmapW(g_hInstance,
MAKEINTRESOURCEW(IDB_ROOT_IMAGE));
if (hRootImage == NULL) return FALSE;
// Add this bitmap to the device image list. This is a bit hacky, but it's safe
m_ClassImage = ImageList_Add(m_ImageListData->ImageList,
hRootImage,
NULL);
DeleteObject(hRootImage);
// Get the root instance
CONFIGRET cr;
cr = CM_Locate_DevNodeW(&m_DevInst,
NULL,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
{
return false;
}
// The root name is the computer name
DWORD Size = DISPLAY_NAME_LEN;
if (GetComputerNameW(m_DisplayName, &Size))
_wcslwr_s(m_DisplayName);
return true;
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "Node.h"
class CRootNode : public CNode
{
private:
DEVINST m_DevInst;
public:
CRootNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData);
~CRootNode();
virtual bool SetupNode();
DEVINST GetDeviceInst() { return m_DevInst; }
};

View file

@ -6,18 +6,7 @@ BEGIN
BEGIN BEGIN
MENUITEM "E&xit", IDC_EXIT MENUITEM "E&xit", IDC_EXIT
END END
POPUP "Action" MENUITEM "Action" IDC_ACTIONMENU
BEGIN
MENUITEM "Update driver software..." IDC_UPDATE_DRV
MENUITEM "Enable" IDC_ENABLE_DRV
MENUITEM "Disable" IDC_DISABLE_DRV
MENUITEM "Uninstall" IDC_UNINSTALL_DRV
MENUITEM SEPARATOR
MENUITEM "Scan for hardware changes" IDC_SCAN_HARDWARE
MENUITEM "Add hardware" IDC_ADD_HARDWARE, GRAYED
MENUITEM SEPARATOR
MENUITEM "Properties", IDC_PROPERTIES
END
POPUP "View" POPUP "View"
BEGIN BEGIN
MENUITEM "Devices by type", IDC_DEVBYTYPE MENUITEM "Devices by type", IDC_DEVBYTYPE