From c3558fc84a7a45fd9f4fbeba92cd2a78be2d1d45 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Thu, 7 Aug 2014 15:21:24 +0000 Subject: [PATCH] [SHELL32] * Populate edit and view menu on first activation. TODO: enable/disable edit menu items in OnInitMenuPopup. * Add Edit menu to resources (en-US only, other langs TODO) * Repurpose BuildFileMenu to build the menu for the selection. This needs improvements as it uses all the items from the context menu at the moment. * Add items to the File menu when shown. svn path=/branches/shell-experiments/; revision=63836 --- dll/win32/browseui/shellbrowser.cpp | 64 ++++++++- dll/win32/shell32/lang/en-US.rc | 17 +++ dll/win32/shell32/shlview.cpp | 198 +++++++++++++++++----------- dll/win32/shell32/shresdef.h | 2 + 4 files changed, 202 insertions(+), 79 deletions(-) diff --git a/dll/win32/browseui/shellbrowser.cpp b/dll/win32/browseui/shellbrowser.cpp index a2b04444243..89a99595a55 100644 --- a/dll/win32/browseui/shellbrowser.cpp +++ b/dll/win32/browseui/shellbrowser.cpp @@ -33,6 +33,47 @@ extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow); #include "newatlinterfaces.h" +static void DbgDumpMenuInternal(HMENU hmenu, char* padding, int padlevel) +{ + WCHAR label[128]; + + padding[padlevel] = '.'; + padding[padlevel + 1] = '.'; + padding[padlevel + 2] = 0; + + int count = GetMenuItemCount(hmenu); + for (int i = 0; i < count; i++) + { + MENUITEMINFOW mii = { 0 }; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU | MIIM_STATE | MIIM_ID; + mii.dwTypeData = label; + mii.cch = _countof(label); + + GetMenuItemInfo(hmenu, i, TRUE, &mii); + + if (mii.fType & MFT_BITMAP) + DbgPrint("%s%2d - %08x: BITMAP %08p (state=%d, has submenu=%s)\n", padding, i, mii.wID, mii.hbmpItem, mii.fState, mii.hSubMenu ? "TRUE" : "FALSE"); + else if (mii.fType & MFT_SEPARATOR) + DbgPrint("%s%2d - %08x ---SEPARATOR---\n", padding, i, mii.wID); + else + DbgPrint("%s%2d - %08x: %S (state=%d, has submenu=%s)\n", padding, i, mii.wID, mii.dwTypeData, mii.fState, mii.hSubMenu ? "TRUE" : "FALSE"); + + if (mii.hSubMenu) + DbgDumpMenuInternal(mii.hSubMenu, padding, padlevel + 2); + + } + + padding[padlevel] = 0; +} + +static void DbgDumpMenu(HMENU hmenu) +{ + char padding[128]; + DbgDumpMenuInternal(hmenu, padding, 0); +} + /* TODO: **Provide implementation of new and delete that use LocalAlloc @@ -1851,8 +1892,18 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::ContextSensitiveHelp(BOOL fEnterMode) HRESULT STDMETHODCALLTYPE CShellBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) { HMENU mainMenu = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU)); + + //DbgPrint("Menu from shell32:\n"); + //DbgDumpMenu(hmenuShared); + + //DbgPrint("Menu from browseui:\n"); + //DbgDumpMenu(mainMenu); + Shell_MergeMenus(hmenuShared, mainMenu, 0, 0, FCIDM_BROWSERLAST, MM_SUBMENUSHAVEIDS); + //DbgPrint("Merged menu:\n"); + //DbgDumpMenu(hmenuShared); + int GCCU(itemCount3) = GetMenuItemCount(hmenuShared); Unused(itemCount3); @@ -1869,6 +1920,9 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU h CComPtr shellMenu; HRESULT hResult; + //DbgPrint("SetMenuSB:\n"); + //DbgDumpMenu(hmenuShared); + if (hmenuShared && IsMenu(hmenuShared) == FALSE) return E_FAIL; hResult = GetMenuBand(IID_PPV_ARG(IShellMenu, &shellMenu)); @@ -3192,7 +3246,15 @@ LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, menuIndex = 5; } - return RelayMsgToShellView(uMsg, wParam, menuIndex, bHandled); + //DbgPrint("Before relay:\n"); + //DbgDumpMenu(theMenu); + + LRESULT ret = RelayMsgToShellView(uMsg, wParam, menuIndex, bHandled); + + //DbgPrint("After relay:\n"); + //DbgDumpMenu(theMenu); + + return ret; } LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) diff --git a/dll/win32/shell32/lang/en-US.rc b/dll/win32/shell32/lang/en-US.rc index d486874ac65..2ab2a253e23 100644 --- a/dll/win32/shell32/lang/en-US.rc +++ b/dll/win32/shell32/lang/en-US.rc @@ -41,6 +41,23 @@ BEGIN END END +/* menubar EDIT menu */ +MENU_003 MENU +BEGIN + MENUITEM "&Undo\tCtrl+Z", FCIDM_SHVIEW_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", FCIDM_SHVIEW_CUT + MENUITEM "&Copy\tCtrl+C", FCIDM_SHVIEW_COPY + MENUITEM "&Paste\tCtrl+V", FCIDM_SHVIEW_INSERT + MENUITEM "Paste &shortcut", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + MENUITEM "Copy to &folder...", FCIDM_SHVIEW_COPYTO + MENUITEM "Mo&ve to folder...", FCIDM_SHVIEW_MOVETO + MENUITEM SEPARATOR + MENUITEM "Select &all\tCtrl+A", FCIDM_SHVIEW_SELECTALL + MENUITEM "&Invert Selection", FCIDM_SHVIEW_INVERTSELECTION +END + /* shellview item menu */ MENU_SHV_FILE MENU BEGIN diff --git a/dll/win32/shell32/shlview.cpp b/dll/win32/shell32/shlview.cpp index 76133420162..edb6b353c2d 100644 --- a/dll/win32/shell32/shlview.cpp +++ b/dll/win32/shell32/shlview.cpp @@ -87,6 +87,7 @@ class CDefView : HWND m_hWndParent; FOLDERSETTINGS m_FolderSettings; HMENU m_hMenu; + BOOL m_menusLoaded; UINT m_uState; UINT m_cidl; LPITEMIDLIST *m_apidl; @@ -125,8 +126,8 @@ class CDefView : static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); HRESULT FillList(); HMENU BuildFileMenu(); - void MergeFileMenu(HMENU hSubMenu); - void MergeViewMenu(HMENU hSubMenu); + void PrepareShowFileMenu(HMENU hSubMenu); + void PrepareShowViewMenu(HMENU hSubMenu); UINT GetSelections(); HRESULT OpenSelectedItems(); void OnDeactivate(); @@ -360,6 +361,7 @@ CDefView::CDefView() m_FolderSettings.fFlags = 0; m_FolderSettings.ViewMode = 0; m_hMenu = NULL; + m_menusLoaded = FALSE; m_uState = 0; m_cidl = 0; m_apidl = NULL; @@ -999,56 +1001,34 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl * #### Handling of the menus #### */ -/********************************************************** -* ShellView_BuildFileMenu() -*/ HMENU CDefView::BuildFileMenu() -{ WCHAR szText[MAX_PATH]; - MENUITEMINFOW mii; - int nTools, i; - HMENU hSubMenu; +{ + HRESULT hr; + CComPtr cm; - TRACE("(%p)\n", this); + GetSelections(); - hSubMenu = CreatePopupMenu(); - if (hSubMenu) - { - /*get the number of items in our global array*/ - for(nTools = 0; Tools[nTools].idCommand != -1; nTools++) {} + LPCITEMIDLIST * apidl = (LPCITEMIDLIST *)m_apidl; - /*add the menu items*/ - for(i = 0; i < nTools; i++) - { - LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); + hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, apidl, IID_NULL_PPV_ARG(IContextMenu, &cm)); + if (FAILED(hr)) + return NULL; - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; + HMENU hmenu = CreatePopupMenu(); - if(BTNS_SEP != Tools[i].bStyle) /* no separator*/ - { - mii.fType = MFT_STRING; - mii.fState = MFS_ENABLED; - mii.dwTypeData = szText; - mii.wID = Tools[i].idCommand; - } - else - { - mii.fType = MFT_SEPARATOR; - } - /* tack This item onto the end of the menu */ - InsertMenuItemW(hSubMenu, (UINT) - 1, TRUE, &mii); - } - } + //FIXME: get proper numbers ? + const UINT first = 0x7800; + const UINT last = 0x7A00; + hr = cm->QueryContextMenu(hmenu, 0, first, last, 0); + if (FAILED(hr)) + return NULL; - TRACE("-- return (menu=%p)\n", hSubMenu); - return hSubMenu; + // TODO: filter or something + + return hmenu; } -/********************************************************** -* ShellView_MergeFileMenu() -*/ -void CDefView::MergeFileMenu(HMENU hSubMenu) +void CDefView::PrepareShowFileMenu(HMENU hSubMenu) { TRACE("(%p)->(submenu=%p) stub\n", this, hSubMenu); @@ -1075,44 +1055,23 @@ void CDefView::MergeFileMenu(HMENU hSubMenu) /* Insert This item at the beginning of the menu. */ _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM+4, MFT_STRING, L"Properties", MFS_DISABLED); - _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM+3, MFT_STRING, L"Rename", MFS_DISABLED); - _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM+2, MFT_STRING, L"Delete", MFS_DISABLED); - _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM+1, MFT_STRING, L"Create Shortcut", MFS_DISABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 4, MFT_STRING, L"Properties", MFS_DISABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 3, MFT_STRING, L"Rename", MFS_DISABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 2, MFT_STRING, L"Delete", MFS_DISABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 1, MFT_STRING, L"Create Shortcut", MFS_DISABLED); _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"New", MFS_ENABLED); - TRACE("--\n"); -} - -/********************************************************** -* ShellView_MergeViewMenu() -*/ -void CDefView::MergeViewMenu(HMENU hSubMenu) -{ - TRACE("(%p)->(submenu=%p)\n", this, hSubMenu); - - if (!hSubMenu) - return; - - // FIXME: I believe windows has all of the items initially in the menu, - // and actively calls DeleteMenu on the items that should not be disaplyed. - - MENUITEMINFOW mii = { 0 }; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_ID | MIIM_STATE; - if (::GetMenuItemInfoW(hSubMenu, FCIDM_SHVIEW_BIGICON, FALSE, &mii) == 0) + HMENU menubase = BuildFileMenu(); + if (menubase) { - HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_001"); + int count = ::GetMenuItemCount(menubase); - _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); - - INT count = ::GetMenuItemCount(menubase); for (int i = 0; i < count; i++) { WCHAR label[128]; - ZeroMemory(&mii, sizeof(mii)); + MENUITEMINFOW mii = { 0 }; mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE; mii.dwTypeData = label; @@ -1123,11 +1082,22 @@ void CDefView::MergeViewMenu(HMENU hSubMenu) mii.fType |= MFT_RADIOCHECK; - ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); + ::InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, &mii); } + _InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + ::DestroyMenu(menubase); } + TRACE("--\n"); +} + +void CDefView::PrepareShowViewMenu(HMENU hSubMenu) +{ + TRACE("(%p)->(submenu=%p)\n", this, hSubMenu); + + if (!hSubMenu) + return; if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST) { @@ -1422,8 +1392,80 @@ void CDefView::DoActivate(UINT uState) { if(m_hMenu) { - TRACE("-- before fnSetMenuSB\n"); - m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd); + if (!m_menusLoaded) + { + MENUITEMINFOW mii = { 0 }; + + /* initialize EDIT menu */ + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii)) + { + HMENU hSubMenu = mii.hSubMenu; + + HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_003"); + + int count = ::GetMenuItemCount(menubase); + for (int i = 0; i < count; i++) + { + WCHAR label[128]; + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE; + mii.dwTypeData = label; + mii.cch = _countof(label); + ::GetMenuItemInfoW(menubase, i, TRUE, &mii); + + DbgPrint("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType); + + mii.fType |= MFT_RADIOCHECK; + + ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); + } + + ::DestroyMenu(menubase); + } + + /* initialize VIEW menu */ + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii)) + { + HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_001"); + + HMENU hSubMenu = mii.hSubMenu; + + _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + + int count = ::GetMenuItemCount(menubase); + for (int i = 0; i < count; i++) + { + WCHAR label[128]; + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE; + mii.dwTypeData = label; + mii.cch = _countof(label); + ::GetMenuItemInfoW(menubase, i, TRUE, &mii); + + DbgPrint("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType); + + mii.fType |= MFT_RADIOCHECK; + + ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); + } + + ::DestroyMenu(menubase); + } + + + TRACE("-- before fnSetMenuSB\n"); + m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd); + + m_menusLoaded = TRUE; + } } if (SVUIA_ACTIVATE_FOCUS == uState) @@ -1900,13 +1942,13 @@ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL switch (menuItemId) { case FCIDM_MENU_FILE: - MergeFileMenu(hSubmenu); + PrepareShowFileMenu(hSubmenu); break; case FCIDM_MENU_EDIT: - //MergeEditMenu(hSubmenu); + //PrepareShowEditMenu(hSubmenu); break; case FCIDM_MENU_VIEW: - MergeViewMenu(hSubmenu); + PrepareShowViewMenu(hSubmenu); break; } diff --git a/dll/win32/shell32/shresdef.h b/dll/win32/shell32/shresdef.h index d94b1b38452..4fecf9badf7 100644 --- a/dll/win32/shell32/shresdef.h +++ b/dll/win32/shell32/shresdef.h @@ -492,6 +492,8 @@ #define FCIDM_SHVIEW_INSERT 0x701A #define FCIDM_SHVIEW_UNDO 0x701B #define FCIDM_SHVIEW_INSERTLINK 0x701C +#define FCIDM_SHVIEW_COPYTO 0x701E +#define FCIDM_SHVIEW_MOVETO 0x701F #define FCIDM_SHVIEW_SELECTALL 0x7021 #define FCIDM_SHVIEW_INVERTSELECTION 0x7022