[RSHELL]
[reactos.git] / base / shell / rshell / CStartMenu.cpp
index fe97909..da990fa 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
 #include "precomp.h"
 
-/* NOTE: The following constants may *NOT* be changed because
+//#define TEST_TRACKPOPUPMENU_SUBMENUS
+
+
+/* NOTE: The following constants *MUST NOT* be changed because
          they're hardcoded and need to be the exact values
          in order to get the start menu to work! */
+#define IDM_RUN                     401
+#define IDM_LOGOFF                  402
+#define IDM_UNDOCKCOMPUTER          410
+#define IDM_TASKBARANDSTARTMENU     413
+#define IDM_LASTSTARTMENU_SEPARATOR 450
+#define IDM_DOCUMENTS               501
+#define IDM_HELPANDSUPPORT          503
 #define IDM_PROGRAMS                504
+#define IDM_CONTROLPANEL            505
+#define IDM_SHUTDOWN                506
 #define IDM_FAVORITES               507
-#define IDM_DOCUMENTS               501
 #define IDM_SETTINGS                508
-#define IDM_CONTROLPANEL            505
-#define IDM_SECURITY                5001
-#define IDM_NETWORKCONNECTIONS      557
 #define IDM_PRINTERSANDFAXES        510
-#define IDM_TASKBARANDSTARTMENU     413
 #define IDM_SEARCH                  520
-#define IDM_HELPANDSUPPORT          503
-#define IDM_RUN                     401
 #define IDM_SYNCHRONIZE             553
-#define IDM_LOGOFF                  402
+#define IDM_NETWORKCONNECTIONS      557
 #define IDM_DISCONNECT              5000
-#define IDM_UNDOCKCOMPUTER          410
-#define IDM_SHUTDOWN                506
-#define IDM_LASTSTARTMENU_SEPARATOR 450
+#define IDM_SECURITY                5001
 
 /*
  * TODO:
  * 1. append the start menu contents from all users
  * 2. implement the context menu for start menu entries (programs, control panel, network connetions, printers)
  * 3. filter out programs folder from the shell folder part of the start menu
+ * 4. showing the programs start menu is SLOW compared to windows. this needs some investigation
  */
 
-class CShellMenuCallback : 
+class CShellMenuCallback :
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public IShellMenuCallback 
+    public IShellMenuCallback
 {
 private:
-    
+
     HWND m_hwndTray;
     CComPtr<IShellMenu> m_pShellMenu;
     CComPtr<IBandSite> m_pBandSite;
@@ -72,7 +75,11 @@ private:
         hr = IUnknown_GetSite(m_pDeskBar, IID_PPV_ARG(ITrayPriv, &m_pTrayPriv));
         hr = IUnknown_GetWindow(m_pTrayPriv, &m_hwndTray);
         hr = m_pTrayPriv->AppendMenuW(&hmenu);
+#ifndef TEST_TRACKPOPUPMENU_SUBMENUS
         hr = m_pShellMenu->SetMenu(hmenu, NULL, SMSET_BOTTOM);
+#else
+        hr = m_pShellMenu->SetMenu(hmenu, m_hwndTray, SMSET_BOTTOM);
+#endif
 
         return hr;
     }
@@ -80,34 +87,50 @@ private:
     HRESULT OnGetInfo(LPSMDATA psmd, SMINFO *psminfo)
     {
         int iconIndex = 0;
-                
+
         switch (psmd->uId)
         {
-        case IDM_PROGRAMS:  iconIndex = -20; break;
-        case IDM_FAVORITES: iconIndex = -173; break;
-        case IDM_DOCUMENTS: iconIndex = -21; break;
-        case IDM_SETTINGS: iconIndex = -22; break;
+            // Smaller "24x24" icons used for the start menu
+            // The bitmaps are still 32x32, but the image is centered
+        case IDM_FAVORITES: iconIndex = -322; break;
+        case IDM_SEARCH: iconIndex = -323; break;
+        case IDM_HELPANDSUPPORT: iconIndex = -324; break;
+        case IDM_LOGOFF: iconIndex = -325; break;
+        case IDM_PROGRAMS:  iconIndex = -326; break;
+        case IDM_DOCUMENTS: iconIndex = -327; break;
+        case IDM_RUN: iconIndex = -328; break;
+        case IDM_SHUTDOWN: iconIndex = -329; break;
+        case IDM_SETTINGS: iconIndex = -330; break;
+
         case IDM_CONTROLPANEL: iconIndex = -22; break;
-        //case IDM_SECURITY: iconIndex = -21; break;
         case IDM_NETWORKCONNECTIONS: iconIndex = -257; break;
         case IDM_PRINTERSANDFAXES: iconIndex = -138; break;
         case IDM_TASKBARANDSTARTMENU: iconIndex = -40; break;
-        case IDM_SEARCH: iconIndex = -23; break;
-        case IDM_HELPANDSUPPORT: iconIndex = -24; break;
-        case IDM_RUN: iconIndex = -25; break;
+        //case IDM_SECURITY: iconIndex = -21; break;
         //case IDM_SYNCHRONIZE: iconIndex = -21; break;
-        case IDM_LOGOFF: iconIndex = -45; break;
         //case IDM_DISCONNECT: iconIndex = -21; break;
         //case IDM_UNDOCKCOMPUTER: iconIndex = -21; break;
-        case IDM_SHUTDOWN: iconIndex = -28; break;
         default:
             return S_FALSE;
         }
 
         if (iconIndex)
         {
-            psminfo->dwMask = SMIM_ICON;
-            psminfo->iIcon = Shell_GetCachedImageIndex(L"shell32.dll", iconIndex, FALSE); 
+            if ((psminfo->dwMask & SMIM_TYPE) != 0)
+                psminfo->dwType = SMIT_STRING;
+            if ((psminfo->dwMask & SMIM_ICON) != 0)
+                psminfo->iIcon = Shell_GetCachedImageIndex(L"shell32.dll", iconIndex, FALSE);
+            if ((psminfo->dwMask & SMIM_FLAGS) != 0)
+                psminfo->dwFlags |= SMIF_ICON;
+#ifdef TEST_TRACKPOPUPMENU_SUBMENUS
+            if ((psminfo->dwMask & SMIM_FLAGS) != 0)
+                psminfo->dwFlags |= SMIF_TRACKPOPUP;
+#endif
+        }
+        else
+        {
+            if ((psminfo->dwMask & SMIM_TYPE) != 0)
+                psminfo->dwType = SMIT_SEPARATOR;
         }
         return S_OK;
     }
@@ -117,7 +140,7 @@ private:
         HRESULT hr;
         int csidl = 0;
         IShellMenu *pShellMenu;
-        
+
         switch (psmd->uId)
         {
         case IDM_PROGRAMS:  csidl = CSIDL_PROGRAMS; break;
@@ -125,10 +148,21 @@ private:
         case IDM_DOCUMENTS: csidl = CSIDL_RECENT; break;
         }
 
+#if USE_SYSTEM_MENUBAND
         hr = CoCreateInstance(CLSID_MenuBand,
-                                NULL,
-                                CLSCTX_INPROC_SERVER,
-                                IID_PPV_ARG(IShellMenu,&pShellMenu));
+            NULL,
+            CLSCTX_INPROC_SERVER,
+            IID_PPV_ARG(IShellMenu, &pShellMenu));
+#else
+        hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &pShellMenu));
+#endif
+        if (FAILED(hr))
+            return hr;
+#if WRAP_MENUBAND
+        hr = CMenuBand_Wrapper(pShellMenu, IID_PPV_ARG(IShellMenu, &pShellMenu));
+        if (FAILED(hr))
+            return hr;
+#endif
 
         hr = pShellMenu->Initialize(this, 0, ANCESTORDEFAULT, SMINIT_VERTICAL);
 
@@ -148,7 +182,7 @@ private:
             MENUITEMINFO mii;
             mii.cbSize = sizeof(mii);
             mii.fMask = MIIM_SUBMENU;
-            if (GetMenuItemInfoW( psmd->hmenu, psmd->uId, FALSE, &mii))
+            if (GetMenuItemInfoW(psmd->hmenu, psmd->uId, FALSE, &mii))
             {
                 hr = pShellMenu->SetMenu(mii.hSubMenu, NULL, SMSET_BOTTOM);
             }
@@ -159,7 +193,7 @@ private:
     HRESULT OnGetContextMenu(LPSMDATA psmd, REFIID iid, void ** pv)
     {
         if (psmd->uId == IDM_PROGRAMS ||
-            psmd->uId == IDM_CONTROLPANEL || 
+            psmd->uId == IDM_CONTROLPANEL ||
             psmd->uId == IDM_NETWORKCONNECTIONS ||
             psmd->uId == IDM_PRINTERSANDFAXES)
         {
@@ -171,9 +205,9 @@ private:
 
     HRESULT OnGetObject(LPSMDATA psmd, REFIID iid, void ** pv)
     {
-        if (IsEqualIID(iid , IID_IShellMenu))
+        if (IsEqualIID(iid, IID_IShellMenu))
             return OnGetSubMenu(psmd, iid, pv);
-        else if (IsEqualIID( iid, IID_IContextMenu))
+        else if (IsEqualIID(iid, IID_IContextMenu))
             return OnGetContextMenu(psmd, iid, pv);
 
         return S_FALSE;
@@ -181,14 +215,14 @@ private:
 
     HRESULT OnExec(LPSMDATA psmd)
     {
-        if(psmd->uId == IDM_CONTROLPANEL)
-            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", NULL,NULL, 1);
-        else if(psmd->uId == IDM_NETWORKCONNECTIONS)
-            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", NULL,NULL, 1);
-        else if(psmd->uId == IDM_PRINTERSANDFAXES)
-            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", NULL,NULL, 1);
+        if (psmd->uId == IDM_CONTROLPANEL)
+            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", NULL, NULL, 1);
+        else if (psmd->uId == IDM_NETWORKCONNECTIONS)
+            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", NULL, NULL, 1);
+        else if (psmd->uId == IDM_PRINTERSANDFAXES)
+            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", NULL, NULL, 1);
         else
-            PostMessageW( m_hwndTray, WM_COMMAND, psmd->uId, 0);
+            PostMessageW(m_hwndTray, WM_COMMAND, psmd->uId, 0);
 
         return S_OK;
     }
@@ -201,7 +235,7 @@ public:
         COM_INTERFACE_ENTRY_IID(IID_IShellMenuCallback, IShellMenuCallback)
     END_COM_MAP()
 
-    void Initialize(    
+    void Initialize(
         IShellMenu* pShellMenu,
         IBandSite* pBandSite,
         IDeskBar* pDeskBar)
@@ -227,46 +261,52 @@ public:
         switch (uMsg)
         {
         case SMC_INITMENU:
-                return OnInitMenu();
+            return OnInitMenu();
         case SMC_GETINFO:
-                return OnGetInfo(psmd, reinterpret_cast<SMINFO*>(lParam));
+            return OnGetInfo(psmd, reinterpret_cast<SMINFO*>(lParam));
         case SMC_GETOBJECT:
-                return OnGetObject(psmd, *reinterpret_cast<IID *>(wParam), reinterpret_cast<void **>(lParam));
+            return OnGetObject(psmd, *reinterpret_cast<IID *>(wParam), reinterpret_cast<void **>(lParam));
         case SMC_EXEC:
-                return OnExec(psmd);
+            return OnExec(psmd);
         case SMC_SFEXEC:
-                m_pTrayPriv->Execute(psmd->psf, psmd->pidlItem);
-                break;
+            m_pTrayPriv->Execute(psmd->psf, psmd->pidlItem);
+            break;
         }
 
-    return S_FALSE;
+        return S_FALSE;
     }
 };
 
-extern "C" 
-HRESULT
-CStartMenu_Constructor(
-    REFIID riid,
-    void **ppv)
+extern "C"
+HRESULT WINAPI
+CStartMenu_Constructor(REFIID riid, void **ppv)
 {
     IShellMenu* pShellMenu;
     IBandSite* pBandSite;
     IDeskBar* pDeskBar;
-    IShellMenuCallback* callback;
     LPITEMIDLIST pidlStartMenu;
 
     HRESULT hr;
     IShellFolder *shellFolder;
     IShellFolder *psfStartMenu;
 
+#if USE_SYSTEM_MENUBAND
     hr = CoCreateInstance(CLSID_MenuBand,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_PPV_ARG(IShellMenu, &pShellMenu));
+#else
+    hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &pShellMenu));
+#endif
+    if (FAILED(hr))
+        return hr;
+#if WRAP_MENUBAND
+    hr = CMenuBand_Wrapper(pShellMenu, IID_PPV_ARG(IShellMenu, &pShellMenu));
     if (FAILED(hr))
-        return NULL;
+        return hr;
+#endif
 
-#if 1
+#if USE_SYSTEM_MENUSITE
     hr = CoCreateInstance(CLSID_MenuBandSite,
                           NULL,
                           CLSCTX_INPROC_SERVER,
@@ -275,44 +315,56 @@ CStartMenu_Constructor(
     hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
 #endif
     if (FAILED(hr))
-        return NULL;
+        return hr;
+#if WRAP_MENUSITE
+    hr = CMenuSite_Wrapper(pBandSite, IID_PPV_ARG(IBandSite, &pBandSite));
+    if (FAILED(hr))
+        return hr;
+#endif
 
+#if USE_SYSTEM_MENUDESKBAR
     hr = CoCreateInstance(CLSID_MenuDeskBar,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_PPV_ARG(IDeskBar, &pDeskBar));
+#else
+    hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
+#endif
     if (FAILED(hr))
-        return NULL;
-    
+        return hr;
+#if WRAP_MENUDESKBAR
+    hr = CMenuDeskBar_Wrapper(pDeskBar, IID_PPV_ARG(IDeskBar, &pDeskBar));
+    if (FAILED(hr))
+        return hr;
+#endif
+
     CComObject<CShellMenuCallback> *pCallback;
     hr = CComObject<CShellMenuCallback>::CreateInstance(&pCallback);
     if (FAILED(hr))
-        return FALSE;
+        return hr;
     pCallback->AddRef(); // CreateInstance returns object with 0 ref count */
     pCallback->Initialize(pShellMenu, pBandSite, pDeskBar);
-    callback = pCallback;
-
-    hr = CShellMenuCallback::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellMenuCallback, &callback)); 
-    if (FAILED(hr))
-        return NULL;
 
-    pShellMenu->Initialize(pCallback, -1, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL);
+    pShellMenu->Initialize(pCallback, (UINT)-1, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL);
     if (FAILED(hr))
-        return NULL;
+        return hr;
 
+    /* FIXME: Use CLSID_MergedFolder class and IID_IAugmentedShellFolder2 interface here */
+    /* CLSID_MergedFolder 26fdc864-be88-46e7-9235-032d8ea5162e */
+    /* IID_IAugmentedShellFolder2 8db3b3f4-6cfe-11d1-8ae9-00c04fd918d0 */
     hr = SHGetFolderLocation(NULL, CSIDL_STARTMENU, 0, 0, &pidlStartMenu);
     hr = SHGetDesktopFolder(&shellFolder);
-    hr = shellFolder->BindToObject(pidlStartMenu, NULL, IID_IShellFolder, (void**)&psfStartMenu);
+    hr = shellFolder->BindToObject(pidlStartMenu, NULL, IID_IShellFolder, (void**) &psfStartMenu);
 
     hr = pShellMenu->SetShellFolder(psfStartMenu, NULL, NULL, 0);
-    
-    hr =  pDeskBar->SetClient(pBandSite);
+
+    hr = pDeskBar->SetClient(pBandSite);
     if (FAILED(hr))
-        return NULL;
+        return hr;
 
-    hr =  pBandSite->AddBand(pShellMenu);
+    hr = pBandSite->AddBand(pShellMenu);
     if (FAILED(hr))
-        return NULL;
+        return hr;
 
     return pDeskBar->QueryInterface(riid, ppv);
 }