[RSHELL]
[reactos.git] / base / shell / rshell / CMenuToolbars.cpp
index 9cc2eea..aa879a2 100644 (file)
@@ -21,6 +21,7 @@
 #include <windowsx.h>
 #include <commoncontrols.h>
 #include <shlwapi_undoc.h>
+#include <uxtheme.h>
 
 #include "CMenuBand.h"
 #include "CMenuToolbars.h"
@@ -48,7 +49,8 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
     switch (uMsg)
     {
     case WM_COMMAND:
-        return OnCommand(wParam, lParam, theResult);
+        //return OnCommand(wParam, lParam, theResult);
+        return S_OK;
 
     case WM_NOTIFY:
         hdr = reinterpret_cast<LPNMHDR>(lParam);
@@ -61,7 +63,7 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
             return OnPagerCalcSize(reinterpret_cast<LPNMPGCALCSIZE>(hdr));
 
         case TBN_DROPDOWN:
-            return OnCommand(reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem, 0, theResult);
+            return ProcessClick(reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem);
 
         case TBN_HOTITEMCHANGE:
             //return OnHotItemChange(reinterpret_cast<LPNMTBHOTITEM>(hdr), theResult);
@@ -105,7 +107,7 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
         case -714: return S_FALSE;
 
         default:
-            DbgPrint("WM_NOTIFY unknown code %d, %d\n", hdr->code, hdr->idFrom);
+            TRACE("WM_NOTIFY unknown code %d, %d\n", hdr->code, hdr->idFrom);
             return S_OK;
         }
         return S_FALSE;
@@ -131,7 +133,7 @@ LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         return IsTrackedItem(wParam);
     case WM_USER_CHANGETRACKEDITEM:
         m_SubclassOld(hWnd, uMsg, wParam, lParam);
-        return ChangeTrackedItem(wParam, lParam);
+        return ChangeTrackedItem(wParam, LOWORD(lParam), HIWORD(lParam));
 
     case WM_COMMAND:
         OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
@@ -151,7 +153,7 @@ HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable)
     if (m_disableMouseTrack != bDisable)
     {
         m_disableMouseTrack = bDisable;
-        DbgPrint("DisableMouseTrack %d\n", bDisable);
+        TRACE("DisableMouseTrack %d\n", bDisable);
     }
     return S_OK;
 }
@@ -192,13 +194,13 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu
         hdc = cdraw->nmcd.hdc;
 
         // The item with an active submenu gets the CHECKED flag.
-        isHot = m_hotBar == this && (int)cdraw->nmcd.dwItemSpec == m_hotItem;
-        isPopup = m_popupBar == this && (int)cdraw->nmcd.dwItemSpec == m_popupItem;
+        isHot = m_hotBar == this && (int) cdraw->nmcd.dwItemSpec == m_hotItem;
+        isPopup = m_popupBar == this && (int) cdraw->nmcd.dwItemSpec == m_popupItem;
 
-        if (m_initFlags & SMINIT_VERTICAL)
+        if (m_initFlags & SMINIT_VERTICAL || IsAppThemed())
         {
             // Remove HOT and CHECKED flags (will restore HOT if necessary)
-            cdraw->nmcd.uItemState &= ~(CDIS_HOT|CDIS_CHECKED);
+            cdraw->nmcd.uItemState &= ~(CDIS_HOT | CDIS_CHECKED);
 
             // Decide on the colors
             if (isHot || (m_hotItem < 0 && isPopup))
@@ -256,8 +258,8 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu
             // TODO: Support RTL text modes by drawing a leftwards arrow aligned to the left of the control
 
             // "8" is the rightwards dropdown arrow in the Marlett font
-            WCHAR text[] = L"8";
-            
+            WCHAR text [] = L"8";
+
             // Configure the font to draw with Marlett, keeping the current background color as-is
             SelectObject(cdraw->nmcd.hdc, m_marlett);
             SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
@@ -277,12 +279,12 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu
 
 CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
     m_hwnd(NULL),
+    m_hwndToolbar(NULL),
     m_useFlatMenus(FALSE),
     m_SubclassOld(NULL),
     m_disableMouseTrack(FALSE),
     m_timerEnabled(FALSE),
     m_menuBand(menuBand),
-    m_hwndToolbar(NULL),
     m_dwMenuFlags(0),
     m_hasSizes(FALSE),
     m_usePager(usePager),
@@ -356,7 +358,7 @@ HRESULT CMenuToolbarBase::UpdateImageLists()
     HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml));
     if (FAILED_UNEXPECTEDLY(hr))
     {
-        SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0); 
+        SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0);
     }
     else
     {
@@ -464,7 +466,7 @@ HRESULT CMenuToolbarBase::GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegr
         *pMaxSize = m_idealSize;
     if (pIntegralSize)
         *pIntegralSize = m_itemSize;
-    
+
     if (m_hasSizes)
         return S_OK;
 
@@ -475,7 +477,7 @@ HRESULT CMenuToolbarBase::GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegr
     SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0);
     SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&m_idealSize));
     SendMessageW(m_hwndToolbar, TB_GETIDEALSIZE, (m_initFlags & SMINIT_VERTICAL) != 0, reinterpret_cast<LPARAM>(&m_idealSize));
-    
+
     // Obtain the button size, to be used as the integral size
     DWORD size = SendMessageW(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
     m_itemSize.cx = GET_X_LPARAM(size);
@@ -539,7 +541,7 @@ HRESULT CMenuToolbarBase::OnGetInfoTip(NMTBGETINFOTIP * tip)
 
     GetDataFromId(iItem, &index, &dwData);
 
-    return GetInfoTip(tip->pszText, tip->cchTextMax, iItem, index, dwData);
+    return InternalGetTooltip(iItem, index, dwData, tip->pszText, tip->cchTextMax);
 }
 
 HRESULT CMenuToolbarBase::OnPopupTimer(DWORD timerId)
@@ -558,7 +560,7 @@ HRESULT CMenuToolbarBase::OnPopupTimer(DWORD timerId)
         return S_FALSE;
 
     // Returns S_FALSE if the current item did not show a submenu
-    HRESULT hr = PopupItem(m_hotItem);
+    HRESULT hr = PopupItem(m_hotItem, FALSE);
     if (hr != S_FALSE)
         return hr;
 
@@ -594,38 +596,38 @@ HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DW
     // and mouse tracking is disabled.
     if (m_disableMouseTrack && dwFlags & HICF_MOUSE)
     {
-        DbgPrint("Hot item change prevented by DisableMouseTrack\n");
+        TRACE("Hot item change prevented by DisableMouseTrack\n");
         return S_OK;
     }
 
     // Notify the toolbar if the hot-tracking left this toolbar
     if (m_hotBar == this && toolbar != this)
     {
-        SendMessage(m_hwndToolbar, TB_SETHOTITEM, (WPARAM)-1, 0);
+        SendMessage(m_hwndToolbar, TB_SETHOTITEM, (WPARAM) -1, 0);
     }
 
+    TRACE("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, toolbar, item);
     m_hotBar = toolbar;
     m_hotItem = item;
 
     if (m_hotBar == this)
     {
-        if (dwFlags & HICF_MOUSE)
+        if (m_isTrackingPopup && !(m_initFlags & SMINIT_VERTICAL))
+        {
+            // If the menubar has an open submenu, switch to the new item's submenu immediately
+            PopupItem(m_hotItem, FALSE);
+        }
+        else if (dwFlags & HICF_MOUSE)
         {
             // Vertical menus show/hide the submenu after a delay,
-            // but horizontal menubars switch between items instantly,
-            // if they were open.
+            // but only with the mouse.
             if (m_initFlags & SMINIT_VERTICAL)
             {
                 DWORD elapsed = 0;
                 SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
                 SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
                 m_timerEnabled = TRUE;
-                DbgPrint("SetTimer called with m_hotItem=%d\n", m_hotItem);
-            }
-            else if (m_isTrackingPopup)
-            {
-                // If the menubar has an open submenu, switch to the new item's submenu immediately
-                PopupItem(m_hotItem);
+                TRACE("SetTimer called with m_hotItem=%d\n", m_hotItem);
             }
         }
         else
@@ -676,6 +678,9 @@ HRESULT CMenuToolbarBase::IsTrackedItem(INT index)
     if (m_hotBar != this)
         return S_FALSE;
 
+    if (index < 0)
+        return S_FALSE;
+
     if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
         return E_FAIL;
 
@@ -688,20 +693,25 @@ HRESULT CMenuToolbarBase::IsTrackedItem(INT index)
     return S_FALSE;
 }
 
-HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index, BOOL wasTracking)
+HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index, BOOL wasTracking, BOOL mouse)
 {
     TBBUTTON btn;
+
+    if (index < 0)
+    {
+        m_isTrackingPopup = FALSE;
+        return m_menuBand->_ChangeHotItem(NULL, -1, HICF_MOUSE);
+    }
+
     if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
         return E_FAIL;
 
-    DbgPrint("Changing tracked item to %d...\n", index);
+    TRACE("ChangeTrackedItem %d, %d\n", index, wasTracking);
     m_isTrackingPopup = wasTracking;
-    m_menuBand->_ChangeHotItem(this, btn.idCommand, HICF_MOUSE);
-
-    return S_OK;
+    return m_menuBand->_ChangeHotItem(this, btn.idCommand, mouse ? HICF_MOUSE : 0);
 }
 
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* childShellMenu)
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* childShellMenu, BOOL keyInitiated)
 {
     // Calculate the submenu position and exclude area
     RECT rc = { 0 };
@@ -735,7 +745,7 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* child
     m_isTrackingPopup = TRUE;
 
     m_menuBand->_ChangePopupItem(this, iItem);
-    m_menuBand->_OnPopupSubMenu(childShellMenu, &pt, &rcl);
+    m_menuBand->_OnPopupSubMenu(childShellMenu, &pt, &rcl, keyInitiated);
 
     return S_OK;
 }
@@ -747,7 +757,7 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu)
 
     if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
         return E_FAIL;
-    
+
     POINT a = { rc.left, rc.top };
     POINT b = { rc.right, rc.bottom };
 
@@ -772,53 +782,92 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu)
     m_menuBand->_ChangePopupItem(NULL, -1);
     m_isTrackingPopup = FALSE;
 
+    m_menuBand->_ChangeHotItem(NULL, -1, 0);
+
     return S_OK;
 }
 
-HRESULT CMenuToolbarBase::DoContextMenu(IContextMenu* contextMenu)
+HRESULT CMenuToolbarBase::TrackContextMenu(IContextMenu* contextMenu, POINT pt)
 {
-    // Calculate the context menu position
-    DWORD dwPos = GetMessagePos();
-    POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
+    // Cancel submenus
+    m_menuBand->_KillPopupTimers();
+    if (m_popupBar)
+        m_menuBand->_CancelCurrentPopup();
 
-    // Display the submenu
+    // Display the context menu
     return m_menuBand->_TrackContextMenu(contextMenu, pt.x, pt.y);
 }
 
-HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
+HRESULT CMenuToolbarBase::ProcessClick(INT iItem)
 {
     if (m_disableMouseTrack)
     {
-        *theResult = 1;
-        DbgPrint("Item click prevented by DisableMouseTrack\n");
+        TRACE("Item click prevented by DisableMouseTrack\n");
         return S_OK;
     }
 
     // If a button is clicked while a submenu was open, cancel the submenu.
     if (!(m_initFlags & SMINIT_VERTICAL) && m_isTrackingPopup)
     {
-        DbgPrint("OnCommand cancelled because it was tracking submenu.\n");
+        TRACE("OnCommand cancelled because it was tracking submenu.\n");
         return S_FALSE;
     }
-    
-    *theResult = 0;
 
-    m_menuBand->_KillPopupTimers();
-
-    if (PopupItem(wParam) == S_OK)
+    if (PopupItem(iItem, FALSE) == S_OK)
     {
-        DbgPrint("PopupItem returned S_OK\n");
+        TRACE("PopupItem returned S_OK\n");
         return S_FALSE;
     }
 
-    DbgPrint("Executing...\n");
+    TRACE("Executing...\n");
 
-    HRESULT hr = m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
+    return m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
+}
 
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
+HRESULT CMenuToolbarBase::MenuBarMouseDown(INT iIndex)
+{
+    TBBUTTON btn;
+
+    if (m_initFlags & SMINIT_VERTICAL)
+        return S_OK;
+
+    ::SendMessageW(m_hwndToolbar, TB_GETBUTTON, iIndex, reinterpret_cast<LPARAM>(&btn));
+    return ProcessClick(btn.idCommand);
+}
+
+HRESULT CMenuToolbarBase::MenuBarMouseUp(INT iIndex)
+{
+    TBBUTTON btn;
+
+    if (!(m_initFlags & SMINIT_VERTICAL))
+        return S_OK;
+
+    ::SendMessageW(m_hwndToolbar, TB_GETBUTTON, iIndex, reinterpret_cast<LPARAM>(&btn));
+    return ProcessClick(btn.idCommand);
+}
+
+HRESULT CMenuToolbarBase::PrepareExecuteItem(INT iItem)
+{
+    this->m_menuBand->_KillPopupTimers();
+
+    m_executeItem = iItem;
+    return GetDataFromId(iItem, &m_executeIndex, &m_executeData);
+}
 
-    return OnCommandInternal(wParam, lParam, theResult);
+HRESULT CMenuToolbarBase::ExecuteItem()
+{
+    return InternalExecuteItem(m_executeItem, m_executeItem, m_executeData);
+}
+
+HRESULT CMenuToolbarBase::OnContextMenu(NMMOUSE * rclick)
+{
+    INT iItem = rclick->dwItemSpec;
+    INT index = rclick->dwHitInfo;
+    DWORD_PTR data = rclick->dwItemData;
+
+    GetDataFromId(iItem, &index, &data);
+
+    return InternalContextMenu(iItem, index, data, rclick->pt);
 }
 
 HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
@@ -830,14 +879,6 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
     {
         int count = SendMessage(m_hwndToolbar, TB_BUTTONCOUNT, 0, 0);
 
-        if (m_hotItem >= 0)
-        {
-            TBBUTTONINFO info = { 0 };
-            info.cbSize = sizeof(TBBUTTONINFO);
-            info.dwMask = 0;
-            index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, m_hotItem, reinterpret_cast<LPARAM>(&info));
-        }
-
         if (dwSelectType == VK_HOME)
         {
             index = 0;
@@ -848,26 +889,37 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
             index = count - 1;
             dwSelectType = VK_UP;
         }
-        else if (index < 0)
+        else
         {
-            if (dwSelectType == VK_UP)
-            {
-                index = count - 1;
-            }
-            else if (dwSelectType == VK_DOWN)
+            if (m_hotItem >= 0)
             {
-                index = 0;
+                TBBUTTONINFO info = { 0 };
+                info.cbSize = sizeof(TBBUTTONINFO);
+                info.dwMask = 0;
+                index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, m_hotItem, reinterpret_cast<LPARAM>(&info));
             }
-        }
-        else
-        {
-            if (dwSelectType == VK_UP)
+
+            if (index < 0)
             {
-                index--;
+                if (dwSelectType == VK_UP)
+                {
+                    index = count - 1;
+                }
+                else if (dwSelectType == VK_DOWN)
+                {
+                    index = 0;
+                }
             }
-            else if (dwSelectType == VK_DOWN)
+            else
             {
-                index++;
+                if (dwSelectType == VK_UP)
+                {
+                    index--;
+                }
+                else if (dwSelectType == VK_DOWN)
+                {
+                    index++;
+                }
             }
         }
 
@@ -882,8 +934,16 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
             {
                 if (prev != btn.idCommand)
                 {
-                    DbgPrint("Setting Hot item to %d\n", index);
-                    m_menuBand->_ChangeHotItem(this, index, 0);
+                    TRACE("Setting Hot item to %d\n", index);
+                    if (!(m_initFlags & SMINIT_VERTICAL) && m_isTrackingPopup)
+                    {
+                        HWND tlw;
+                        m_menuBand->_GetTopLevelWindow(&tlw);
+                        SendMessage(tlw, WM_CANCELMODE, 0, 0);
+                        PostMessage(m_hwndToolbar, WM_USER_CHANGETRACKEDITEM, index, MAKELPARAM(m_isTrackingPopup, FALSE));
+                    }
+                    else
+                        m_menuBand->_ChangeHotItem(this, btn.idCommand, 0);
                 }
                 return S_OK;
             }
@@ -897,11 +957,13 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
                 index++;
             }
         }
+
+        return S_FALSE;
     }
 
     if (prev != -1)
     {
-        DbgPrint("Setting Hot item to null\n");
+        TRACE("Setting Hot item to null\n");
         m_menuBand->_ChangeHotItem(NULL, -1, 0);
     }
 
@@ -971,6 +1033,15 @@ HRESULT CMenuToolbarBase::AddPlaceholder()
     return S_OK;
 }
 
+HRESULT CMenuToolbarBase::ClearToolbar()
+{
+    while (SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0))
+    {
+        // empty;
+    }
+    return S_OK;
+}
+
 HRESULT CMenuToolbarBase::GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData)
 {
     if (pData)
@@ -1005,7 +1076,7 @@ HRESULT CMenuToolbarBase::CancelCurrentPopup()
     return m_menuBand->_CancelCurrentPopup();
 }
 
-HRESULT CMenuToolbarBase::PopupItem(INT iItem)
+HRESULT CMenuToolbarBase::PopupItem(INT iItem, BOOL keyInitiated)
 {
     INT index;
     DWORD_PTR dwData;
@@ -1031,11 +1102,11 @@ HRESULT CMenuToolbarBase::PopupItem(INT iItem)
 
     if (!(m_initFlags & SMINIT_VERTICAL))
     {
-        DbgPrint("PopupItem non-vertical %d %d\n", index, iItem);
+        TRACE("PopupItem non-vertical %d %d\n", index, iItem);
         m_menuBand->_ChangeHotItem(this, iItem, 0);
     }
 
-    return InternalPopupItem(iItem, index, dwData);
+    return InternalPopupItem(iItem, index, dwData, keyInitiated);
 }
 
 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
@@ -1044,6 +1115,10 @@ CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
 {
 }
 
+CMenuStaticToolbar::~CMenuStaticToolbar()
+{
+}
+
 HRESULT  CMenuStaticToolbar::GetMenu(
     _Out_opt_ HMENU *phmenu,
     _Out_opt_ HWND *phwnd,
@@ -1077,10 +1152,7 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
 
     if (clearFirst)
     {
-        while (SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0))
-        {
-            // empty;
-        }
+        ClearToolbar();
     }
 
     int count = 0;
@@ -1096,7 +1168,7 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
 
         if (!GetMenuItemInfoW(m_hmenu, i, TRUE, &info))
         {
-            DbgPrint("Error obtaining info for menu item at pos=%d\n", i);
+            TRACE("Error obtaining info for menu item at pos=%d\n", i);
             continue;
         }
 
@@ -1108,7 +1180,6 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
         }
         else if (!(info.fType & MFT_BITMAP))
         {
-
             info.cch++;
             info.dwTypeData = (PWSTR) HeapAlloc(GetProcessHeap(), 0, (info.cch + 1) * sizeof(WCHAR));
 
@@ -1121,7 +1192,10 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
 
             HRESULT hr = m_menuBand->_CallCBWithItemId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo));
             if (FAILED_UNEXPECTEDLY(hr))
+            {
+                delete sminfo;
                 return hr;
+            }
 
             AddButton(info.wID, info.dwTypeData, info.hSubMenu != NULL, sminfo->iIcon, reinterpret_cast<DWORD_PTR>(sminfo), last);
 
@@ -1132,7 +1206,7 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
     return S_OK;
 }
 
-HRESULT CMenuStaticToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuStaticToolbar::InternalGetTooltip(INT iItem, INT index, DWORD_PTR dwData, LPWSTR pszText, INT cchTextMax)
 {
     //SMINFO * info = reinterpret_cast<SMINFO*>(dwData);
     UNIMPLEMENTED;
@@ -1145,22 +1219,23 @@ HRESULT CMenuStaticToolbar::OnDeletingButton(const NMTOOLBAR * tb)
     return S_OK;
 }
 
-HRESULT CMenuStaticToolbar::OnContextMenu(NMMOUSE * rclick)
+HRESULT CMenuStaticToolbar::InternalContextMenu(INT iItem, INT index, DWORD_PTR dwData, POINT pt)
 {
     CComPtr<IContextMenu> contextMenu;
-    HRESULT hr = m_menuBand->_CallCBWithItemId(rclick->dwItemSpec, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IContextMenu), reinterpret_cast<LPARAM>(&contextMenu));
+    HRESULT hr = m_menuBand->_CallCBWithItemId(iItem, SMC_GETOBJECT, 
+        reinterpret_cast<WPARAM>(&IID_IContextMenu), reinterpret_cast<LPARAM>(&contextMenu));
     if (hr != S_OK)
         return hr;
 
-    return DoContextMenu(contextMenu);
+    return TrackContextMenu(contextMenu, pt);
 }
 
-HRESULT CMenuStaticToolbar::OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
+HRESULT CMenuStaticToolbar::InternalExecuteItem(INT iItem, INT index, DWORD_PTR data)
 {
-    return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
+    return m_menuBand->_CallCBWithItemId(iItem, SMC_EXEC, 0, 0);
 }
 
-HRESULT CMenuStaticToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuStaticToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData, BOOL keyInitiated)
 {
     SMINFO * nfo = reinterpret_cast<SMINFO*>(dwData);
     if (!nfo)
@@ -1177,7 +1252,7 @@ HRESULT CMenuStaticToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dw
         if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
-        return PopupSubMenu(iItem, index, shellMenu);
+        return PopupSubMenu(iItem, index, shellMenu, keyInitiated);
     }
 }
 
@@ -1186,7 +1261,6 @@ HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR d
     return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE;
 }
 
-
 CMenuSFToolbar::CMenuSFToolbar(CMenuBand * menuBand) :
     CMenuToolbarBase(menuBand, TRUE),
     m_shellFolder(NULL),
@@ -1206,41 +1280,48 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
     PWSTR MenuString;
 
     IEnumIDList * eidl;
-    m_shellFolder->EnumObjects(m_hwndToolbar, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
+    m_shellFolder->EnumObjects(GetToolbar(), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
 
-    LPITEMIDLIST item = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(sizeof(ITEMIDLIST)));
-    ULONG fetched;
-    hr = eidl->Next(1, &item, &fetched);
-    while (SUCCEEDED(hr) && fetched > 0)
+    LPITEMIDLIST item = NULL;
+    hr = eidl->Next(1, &item, NULL);
+    while (hr == S_OK)
     {
         INT index = 0;
         INT indexOpen = 0;
 
-        STRRET sr = { STRRET_CSTR, { 0 } };
+        if (m_menuBand->_CallCBWithItemPidl(item, 0x10000000, 0, 0) == S_OK)
+        {
+            STRRET sr = { STRRET_CSTR, { 0 } };
 
-        hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
-        if (FAILED_UNEXPECTEDLY(hr))
-            return hr;
+            hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
+            if (FAILED_UNEXPECTEDLY(hr))
+                return hr;
 
-        StrRetToStr(&sr, NULL, &MenuString);
+            StrRetToStr(&sr, NULL, &MenuString);
 
-        index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
+            index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
 
-        LPCITEMIDLIST itemc = item;
+            LPCITEMIDLIST itemc = item;
 
-        SFGAOF attrs = SFGAO_FOLDER;
-        hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
+            SFGAOF attrs = SFGAO_FOLDER;
+            hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
 
-        DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
+            DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
 
-        // Fetch next item already, so we know if the current one is the last
-        hr = eidl->Next(1, &item, &fetched);
+            // Fetch next item already, so we know if the current one is the last
+            hr = eidl->Next(1, &item, NULL);
 
-        AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData, FAILED(hr) || fetched == 0);
+            AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData, hr != S_OK);
 
-        CoTaskMemFree(MenuString);
+            CoTaskMemFree(MenuString);
+        }
+        else
+        {
+            // Fetch next item here also
+            hr = eidl->Next(1, &item, NULL);
+        }
     }
-    CoTaskMemFree(item);
+    ILFree(item);
 
     // If no items were added, show the "empty" placeholder
     if (i == 0)
@@ -1251,7 +1332,7 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
     return hr;
 }
 
-HRESULT CMenuSFToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuSFToolbar::InternalGetTooltip(INT iItem, INT index, DWORD_PTR dwData, LPWSTR pszText, INT cchTextMax)
 {
     //ITEMIDLIST * pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
     UNIMPLEMENTED;
@@ -1293,7 +1374,8 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
             pidl = ILClone(m_idList);
             if (!pidl)
             {
-                (*(IUnknown**) ppv)->Release();
+                ERR("ILClone failed!\n");
+                (*reinterpret_cast<IUnknown**>(ppv))->Release();
                 return E_FAIL;
             }
         }
@@ -1304,29 +1386,29 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
     return hr;
 }
 
-HRESULT CMenuSFToolbar::OnContextMenu(NMMOUSE * rclick)
+HRESULT CMenuSFToolbar::InternalContextMenu(INT iItem, INT index, DWORD_PTR dwData, POINT pt)
 {
     HRESULT hr;
-    CComPtr<IContextMenu> contextMenu;
-    LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(rclick->dwItemData);
+    CComPtr<IContextMenu> contextMenu = NULL;
+    LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(dwData);
 
-    hr = m_shellFolder->GetUIObjectOf(m_hwndToolbar, 1, &pidl, IID_IContextMenu, NULL, reinterpret_cast<VOID **>(&contextMenu));
-    if (hr != S_OK)
+    hr = m_shellFolder->GetUIObjectOf(GetToolbar(), 1, &pidl, IID_NULL_PPV_ARG(IContextMenu, &contextMenu));
+    if (FAILED_UNEXPECTEDLY(hr))
+    {
         return hr;
+    }
+
+    hr = TrackContextMenu(contextMenu, pt);
 
-    return DoContextMenu(contextMenu);
+    return hr;
 }
 
-HRESULT CMenuSFToolbar::OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
+HRESULT CMenuSFToolbar::InternalExecuteItem(INT iItem, INT index, DWORD_PTR data)
 {
-    DWORD_PTR data;
-
-    GetDataFromId(wParam, NULL, &data);
-
     return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(data), SMC_SFEXEC, 0, 0);
 }
 
-HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData)
+HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData, BOOL keyInitiated)
 {
     HRESULT hr;
     UINT uId;
@@ -1340,21 +1422,9 @@ HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData
     if (!pidl)
         return E_FAIL;
 
-#if USE_SYSTEM_MENUBAND
-    hr = CoCreateInstance(CLSID_MenuBand,
-        NULL,
-        CLSCTX_INPROC_SERVER,
-        IID_PPV_ARG(IShellMenu, &shellMenu));
-#else
     hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &shellMenu));
-#endif
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
-#if WRAP_MENUBAND
-    hr = CMenuBand_Wrapper(shellMenu, IID_PPV_ARG(IShellMenu, &shellMenu));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-#endif
 
     m_menuBand->GetMenuInfo(&psmc, &uId, &uIdAncestor, &flags);
 
@@ -1372,7 +1442,7 @@ HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
-    return PopupSubMenu(iItem, index, shellMenu);
+    return PopupSubMenu(iItem, index, shellMenu, keyInitiated);
 }
 
 HRESULT CMenuSFToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData)