[SHELL32]
authorDavid Quintana <gigaherz@gmail.com>
Thu, 7 Aug 2014 15:21:24 +0000 (15:21 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Thu, 7 Aug 2014 15:21:24 +0000 (15:21 +0000)
* 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
dll/win32/shell32/lang/en-US.rc
dll/win32/shell32/shlview.cpp
dll/win32/shell32/shresdef.h

index a2b0444..89a9959 100644 (file)
@@ -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<IShellMenu>                     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)
index d486874..2ab2a25 100644 (file)
@@ -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
index 7613342..edb6b35 100644 (file)
@@ -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<IContextMenu> 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;
     }
 
index d94b1b3..4fecf9b 100644 (file)
 #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