diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp b/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp index d345f467eff..da3415131bd 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp @@ -51,8 +51,7 @@ CDeviceView::CDeviceView( m_hMenu(NULL), m_ViewType(DevicesByType), m_ShowHidden(FALSE), - m_RootClassImage(-1), - m_RootDevInst(0) + m_RootNode(NULL) { ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA)); } @@ -162,14 +161,27 @@ CDeviceView::OnContextMenu( ScreenToClient(m_hTreeView, &pt) && PtInRect(&rc, pt)) { - - INT xPos = GET_X_LPARAM(lParam); - INT yPos = GET_Y_LPARAM(lParam); - CNode *Node = GetSelectedNode(); 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 CDeviceView::HasProperties( _In_ LPTV_ITEMW TvItem @@ -336,54 +364,8 @@ CDeviceView::EnableSelectedDevice( bool CDeviceView::AddRootDevice() { - // Check whether we've loaded the root bitmap into the imagelist (done on first run) - 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); - + m_hTreeRoot = InsertIntoTreeView(NULL, m_RootNode); return (m_hTreeRoot != NULL); - } bool @@ -622,7 +604,7 @@ CDeviceView::ListDevicesByConnection() if (bSuccess == false) return false; // 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 (void)TreeView_Expand(m_hTreeView, @@ -755,11 +737,10 @@ CDeviceView::GetSiblingDevice( HTREEITEM CDeviceView::InsertIntoTreeView( - _In_ HTREEITEM hParent, + _In_opt_ HTREEITEM hParent, _In_ CNode *Node ) { - LPWSTR lpLabel; lpLabel = Node->GetDisplayName(); @@ -791,15 +772,11 @@ CDeviceView::InsertIntoTreeView( } void -CDeviceView::BuildContextMenuForNode( - _In_ CNode *Node, - _In_ INT xPos, - _In_ INT yPos +CDeviceView::BuildActionMenuForNode( + _In_ HMENU OwnerMenu, + _In_ CNode *Node ) { - // Create the context menu - HMENU hContextMenu = CreatePopupMenu(); - // Create a seperator structure MENUITEMINFOW MenuSeperator = { 0 }; MenuSeperator.cbSize = sizeof(MENUITEMINFOW); @@ -824,7 +801,7 @@ CDeviceView::BuildContextMenuForNode( String.LoadStringW(g_hInstance, IDS_MENU_UPDATE); MenuItemInfo.wID = IDC_UPDATE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; } @@ -833,7 +810,7 @@ CDeviceView::BuildContextMenuForNode( String.LoadStringW(g_hInstance, IDS_MENU_ENABLE); MenuItemInfo.wID = IDC_ENABLE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; } @@ -842,7 +819,7 @@ CDeviceView::BuildContextMenuForNode( String.LoadStringW(g_hInstance, IDS_MENU_DISABLE); MenuItemInfo.wID = IDC_DISABLE_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; } @@ -851,11 +828,11 @@ CDeviceView::BuildContextMenuForNode( String.LoadStringW(g_hInstance, IDS_MENU_UNINSTALL); MenuItemInfo.wID = IDC_UNINSTALL_DRV; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; } - InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator); i++; } @@ -863,32 +840,22 @@ CDeviceView::BuildContextMenuForNode( String.LoadStringW(g_hInstance, IDS_MENU_SCAN); MenuItemInfo.wID = IDC_SCAN_HARDWARE; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); i++; if (Node->HasProperties()) { - InsertMenuItemW(hContextMenu, i, TRUE, &MenuSeperator); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator); i++; String.LoadStringW(g_hInstance, IDS_MENU_PROPERTIES); MenuItemInfo.wID = IDC_PROPERTIES; MenuItemInfo.dwTypeData = String.GetBuffer(); - InsertMenuItemW(hContextMenu, i, TRUE, &MenuItemInfo); + InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo); 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 @@ -1097,6 +1064,9 @@ CDeviceView::RefreshDeviceList() EmptyLists(); + if (m_RootNode) delete m_RootNode; + m_RootNode = new CRootNode(&m_ImageListData); + m_RootNode->SetupNode(); // Loop through all the classes do { diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.h b/reactos/dll/win32/devmgr/devmgmt/DeviceView.h index 438d6571f73..24ab2c20db5 100644 --- a/reactos/dll/win32/devmgr/devmgmt/DeviceView.h +++ b/reactos/dll/win32/devmgr/devmgmt/DeviceView.h @@ -1,6 +1,7 @@ #pragma once #include "DeviceNode.h" #include "ClassNode.h" +#include "RootNode.h" enum ViewType { @@ -13,6 +14,7 @@ enum ViewType class CDeviceView { + CRootNode *m_RootNode; CAtlList m_ClassNodeList; CAtlList m_DeviceNodeList; SP_CLASSIMAGELIST_DATA m_ImageListData; @@ -22,9 +24,7 @@ class CDeviceView HMENU m_hMenu; ViewType m_ViewType; HTREEITEM m_hTreeRoot; - DEVINST m_RootDevInst; bool m_ShowHidden; - int m_RootClassImage; public: CDeviceView( @@ -68,6 +68,11 @@ public: ViewType GetCurrentView() { return m_ViewType; } + bool CreateActionMenu( + _In_ HMENU OwnerMenu, + _In_ bool MainMenu + ); + bool HasProperties( _In_ LPTV_ITEMW TvItem ); @@ -123,14 +128,13 @@ private: ); HTREEITEM InsertIntoTreeView( - _In_ HTREEITEM hParent, + _In_opt_ HTREEITEM hParent, _In_ CNode *Node ); - void BuildContextMenuForNode( - _In_ CNode *Node, - _In_ INT xPos, - _In_ INT yPos + void BuildActionMenuForNode( + _In_ HMENU OwnerMenu, + _In_ CNode *Node ); HTREEITEM RecurseFindDevice( diff --git a/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp b/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp index d54a7fcaecf..f96145b68a7 100644 --- a/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp @@ -590,6 +590,29 @@ CMainWindow::OnCommand(WPARAM wParam, 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: { RefreshView(DevicesByType); diff --git a/reactos/dll/win32/devmgr/devmgmt/MainWindow.h b/reactos/dll/win32/devmgr/devmgmt/MainWindow.h index b7bbc78f72a..71f68cc82ab 100644 --- a/reactos/dll/win32/devmgr/devmgmt/MainWindow.h +++ b/reactos/dll/win32/devmgr/devmgmt/MainWindow.h @@ -16,6 +16,7 @@ class CMainWindow HWND m_hToolBar; HIMAGELIST m_ToolbarhImageList; HMENU m_hMenu; + HMENU m_hActionMenu; int m_CmdShow; public: diff --git a/reactos/dll/win32/devmgr/devmgmt/Node.cpp b/reactos/dll/win32/devmgr/devmgmt/Node.cpp index 1289582e543..5d1d5efa193 100644 --- a/reactos/dll/win32/devmgr/devmgmt/Node.cpp +++ b/reactos/dll/win32/devmgr/devmgmt/Node.cpp @@ -22,6 +22,7 @@ CNode::CNode(_In_ NodeType Type, m_ClassImage(0) { m_DisplayName[0] = UNICODE_NULL; + m_ClassGuid = GUID_NULL; } CNode::~CNode() diff --git a/reactos/dll/win32/devmgr/devmgmt/Resource.h b/reactos/dll/win32/devmgr/devmgmt/Resource.h index 8388031c977..f479ce61049 100644 --- a/reactos/dll/win32/devmgr/devmgmt/Resource.h +++ b/reactos/dll/win32/devmgr/devmgmt/Resource.h @@ -21,8 +21,12 @@ #define IDC_UPDATE_DRV 104 #define IDC_UNINSTALL_DRV 105 #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 */ #define IDC_DEVBYTYPE 200 diff --git a/reactos/dll/win32/devmgr/devmgmt/RootNode.cpp b/reactos/dll/win32/devmgr/devmgmt/RootNode.cpp new file mode 100644 index 00000000000..ba1fc80f528 --- /dev/null +++ b/reactos/dll/win32/devmgr/devmgmt/RootNode.cpp @@ -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 +* +*/ + +#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; + + +} \ No newline at end of file diff --git a/reactos/dll/win32/devmgr/devmgmt/RootNode.h b/reactos/dll/win32/devmgr/devmgmt/RootNode.h new file mode 100644 index 00000000000..4c58fc56dd4 --- /dev/null +++ b/reactos/dll/win32/devmgr/devmgmt/RootNode.h @@ -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; } +}; + diff --git a/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc b/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc index eb501e9866b..4a8f1383c57 100644 --- a/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc +++ b/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc @@ -6,18 +6,7 @@ BEGIN BEGIN MENUITEM "E&xit", IDC_EXIT END - POPUP "Action" - 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 + MENUITEM "Action" IDC_ACTIONMENU POPUP "View" BEGIN MENUITEM "Devices by type", IDC_DEVBYTYPE