- 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_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
{

View file

@ -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<CClassNode *> m_ClassNodeList;
CAtlList<CDeviceNode *> 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(

View file

@ -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);

View file

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

View file

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

View file

@ -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

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
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