[RSHELL]
[reactos.git] / base / shell / rshell / CMenuToolbars.cpp
index 7e9cf7c..5fc5b7e 100644 (file)
@@ -34,26 +34,22 @@ HRESULT WINAPI SHGetImageList(
     _Out_  void **ppv
     );
 
-#define TBSTYLE_EX_VERTICAL 4
-
+// FIXME: Enable if/when wine comctl supports this flag properly
+#define USE_TBSTYLE_EX_VERTICAL 0
 
 #define TIMERID_HOTTRACK 1
 #define SUBCLASS_ID_MENUBAND 1
 
+HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable)
+{
+    m_disableMouseTrack = bDisable;
+    return S_OK;
+}
+
 HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
 {
-    RECT rc;
-    HDC hdc;
-    HBRUSH bgBrush;
-    HBRUSH hotBrush;
     NMHDR * hdr;
-    NMTBCUSTOMDRAW * cdraw;
-    NMTBHOTITEM * hot;
-    NMMOUSE * rclick;
     NMPGCALCSIZE* csize;
-    TBBUTTONINFO btni;
-    COLORREF clrText;
-    COLORREF clrTextHighlight;
     SIZE tbs;
 
     *theResult = 0;
@@ -66,6 +62,13 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
         hdr = reinterpret_cast<LPNMHDR>(lParam);
         switch (hdr->code)
         {
+        case TTN_GETDISPINFOA:
+        case TTN_GETDISPINFOW:
+            return S_OK;
+
+        case TBN_DELETINGBUTTON:
+            return OnDeletingButton(reinterpret_cast<LPNMTOOLBAR>(hdr));
+
         case PGN_CALCSIZE:
             csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
 
@@ -85,94 +88,117 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
             return OnCommand(wParam, 0, theResult);
 
         case TBN_HOTITEMCHANGE:
-            hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
-            return OnHotItemChange(hot);
+            return OnHotItemChange(reinterpret_cast<LPNMTBHOTITEM>(hdr), theResult);
 
         case NM_RCLICK:
-            rclick = reinterpret_cast<LPNMMOUSE>(hdr);
-
-            return OnContextMenu(rclick);
+            return OnContextMenu(reinterpret_cast<LPNMMOUSE>(hdr));
 
         case NM_CUSTOMDRAW:
-            cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
-            switch (cdraw->nmcd.dwDrawStage)
-            {
-            case CDDS_PREPAINT:
-                *theResult = CDRF_NOTIFYITEMDRAW;
-                return S_OK;
+            return OnCustomDraw(reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr), theResult);
 
-            case CDDS_ITEMPREPAINT:
-                
-                clrText = GetSysColor(COLOR_MENUTEXT);
-                clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
+        case RBN_CHILDSIZE:
+            return S_OK;
 
-                bgBrush = GetSysColorBrush(COLOR_MENU);
-                hotBrush = GetSysColorBrush(m_useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT);
+        default:
+            DbgPrint("WM_NOTIFY unknown code %d, %d\n", hdr->code, hdr->idFrom);
+        }
+        return S_OK;
+    }
 
-                rc = cdraw->nmcd.rc;
-                hdc = cdraw->nmcd.hdc;
+    return S_FALSE;
+}
 
-                if (((INT) cdraw->nmcd.dwItemSpec == m_hotItem ||
-                    (m_hotItem < 0 && (INT) cdraw->nmcd.dwItemSpec == m_popupItem)))
-                {
-                    cdraw->nmcd.uItemState = CDIS_HOT;
-                }
+HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult)
+{
+    RECT rc;
+    HDC hdc;
+    HBRUSH bgBrush;
+    HBRUSH hotBrush;
+    COLORREF clrText;
+    COLORREF clrTextHighlight;
+    bool isHot, isPopup;
+    TBBUTTONINFO btni;
 
-                switch (cdraw->nmcd.uItemState)
-                {
-                case CDIS_HOT:
-                case CDIS_FOCUS:
-                    FillRect(hdc, &rc, hotBrush);
-                    SetTextColor(hdc, clrTextHighlight);
-                    cdraw->clrText = clrTextHighlight;
-                    break;
-                default:
-                    FillRect(hdc, &rc, bgBrush);
-                    SetTextColor(hdc, clrText);
-                    cdraw->clrText = clrText;
-                    break;
-                }
+    switch (cdraw->nmcd.dwDrawStage)
+    {
+    case CDDS_PREPAINT:
+        if (m_toolbarFlags & SMINIT_VERTICAL)
+            *theResult = CDRF_NOTIFYITEMDRAW;
+        return S_OK;
 
-                cdraw->iListGap += 4;
+    case CDDS_ITEMPREPAINT:
 
-                *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only
-                return S_OK;
+        clrText = GetSysColor(COLOR_MENUTEXT);
+        clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
 
-            case CDDS_ITEMPOSTPAINT:
-                btni.cbSize = sizeof(btni);
-                btni.dwMask = TBIF_STYLE;
-                SendMessage(hWnd, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast<LPARAM>(&btni));
-                if (btni.fsStyle & BTNS_DROPDOWN)
-                {
-                    SelectObject(cdraw->nmcd.hdc, m_marlett);
-                    WCHAR text[] = L"8";
-                    SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
-                    RECT rc = cdraw->nmcd.rc;
-                    rc.right += 1;
-                    DrawTextEx(cdraw->nmcd.hdc, text, 1, &rc, DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE, NULL);
-                }
-                *theResult = TRUE;
-                return S_OK;
-            }
-            return S_OK;
+        bgBrush = GetSysColorBrush(COLOR_MENU);
+        hotBrush = GetSysColorBrush(m_useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT);
+
+        rc = cdraw->nmcd.rc;
+        hdc = cdraw->nmcd.hdc;
+
+        isHot = m_hotBar == this && m_hotItem == static_cast<INT>(cdraw->nmcd.dwItemSpec);
+        isPopup = m_popupBar == this && m_popupItem == static_cast<INT>(cdraw->nmcd.dwItemSpec);
+
+        if (isHot || (m_hotItem < 0 && isPopup))
+        {
+            cdraw->nmcd.uItemState |= CDIS_HOT;
+        }
+        else
+        {
+            cdraw->nmcd.uItemState &= ~CDIS_HOT;
+        }
+
+        if (cdraw->nmcd.uItemState&CDIS_HOT)
+        {
+            FillRect(hdc, &rc, hotBrush);
+            SetTextColor(hdc, clrTextHighlight);
+            cdraw->clrText = clrTextHighlight;
         }
+        else
+        {
+            FillRect(hdc, &rc, bgBrush);
+            SetTextColor(hdc, clrText);
+            cdraw->clrText = clrText;
+        }
+
+        cdraw->iListGap += 4;
+
+        *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only
         return S_OK;
-    }
 
-    return S_FALSE;
+    case CDDS_ITEMPOSTPAINT:
+        btni.cbSize = sizeof(btni);
+        btni.dwMask = TBIF_STYLE;
+        SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast<LPARAM>(&btni));
+        if (btni.fsStyle & BTNS_DROPDOWN)
+        {
+            SelectObject(cdraw->nmcd.hdc, m_marlett);
+            WCHAR text[] = L"8";
+            SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
+            RECT rc = cdraw->nmcd.rc;
+            rc.right += 1;
+            DrawTextEx(cdraw->nmcd.hdc, text, 1, &rc, DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE, NULL);
+        }
+        *theResult = TRUE;
+        return S_OK;
+    }
+    return S_OK;
 }
 
 CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
     m_hwnd(NULL),
     m_useFlatMenus(FALSE),
+    m_SubclassOld(NULL), 
+    m_disableMouseTrack(FALSE),
     m_menuBand(menuBand),
     m_hwndToolbar(NULL),
     m_dwMenuFlags(0),
+    m_hasIdealSize(FALSE),
+    m_usePager(usePager),
     m_hotItem(-1),
     m_popupItem(-1),
-    m_SubclassOld(NULL),
-    m_hasIdealSize(FALSE),
-    m_usePager(usePager)
+    m_isTracking(FALSE)
 {
     m_marlett = CreateFont(
         0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET,
@@ -209,6 +235,13 @@ HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow)
 
 HRESULT CMenuToolbarBase::UpdateImageLists()
 {
+    if ((m_toolbarFlags & (SMINIT_TOPLEVEL| SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) // not vertical.
+    {
+        /* Hide the placeholders for the button images */
+        SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
+        return S_OK;
+    }
+
     int shiml;
     if (m_menuBand->UseBigIcons())
     {
@@ -254,9 +287,15 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags)
     if (dwFlags & SMINIT_VERTICAL)
     {
         tbStyles |= CCS_VERT;
+
+#if USE_TBSTYLE_EX_VERTICAL
+        // FIXME: Use when it works in ros (?)
         tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW;
+#endif
     }
 
+    m_toolbarFlags = dwFlags;
+
     RECT rc;
 
     if (!::GetClientRect(hwndParent, &rc) || (rc.left == rc.right) || (rc.top == rc.bottom))
@@ -302,13 +341,6 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags)
     /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
     SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
 
-    //if (dwFlags & SMINIT_TOPLEVEL)
-    //{
-    //    /* Hide the placeholders for the button images */
-    //    SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
-    //}
-    //else
-
     SetWindowLongPtr(hwndToolbar, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
     m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
 
@@ -340,8 +372,11 @@ HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy)
         SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0);
     }
     SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0);
-    DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
-    SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize)));
+    if (m_toolbarFlags & SMINIT_VERTICAL)
+    {
+        DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
+        SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize)));
+    }
     return S_OK;
 }
 
@@ -363,14 +398,30 @@ LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM w
 
 LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
+    LRESULT lr;
+
     switch (uMsg)
     {
+    case WM_USER_ISTRACKEDITEM:
+        m_SubclassOld(hWnd, uMsg, wParam, lParam);
+        return IsTrackedItem(wParam);
+    case WM_USER_CHANGETRACKEDITEM:
+        m_isTracking = TRUE;
+        m_SubclassOld(hWnd, uMsg, wParam, lParam);
+        return ChangeTrackedItem(wParam);
+
+    case WM_COMMAND:
+        OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
+        break;
+    case WM_NOTIFY:
+        OnWinEvent(hWnd, uMsg, wParam, lParam, &lr);
+        break;
     case WM_TIMER:
         if (wParam == TIMERID_HOTTRACK)
         {
             KillTimer(hWnd, TIMERID_HOTTRACK);
 
-            m_menuBand->_OnPopupSubMenu(-1, NULL, NULL, NULL);
+            m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1);
 
             if (HasSubMenu(m_hotItem) == S_OK)
             {
@@ -382,47 +433,152 @@ LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
     return m_SubclassOld(hWnd, uMsg, wParam, lParam);
 }
 
-HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot)
+HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult)
 {
+    if (m_disableMouseTrack && hot->dwFlags & HICF_MOUSE)
+    {
+        *theResult = 1;
+        return S_OK;
+    }
+
     if (hot->dwFlags & HICF_LEAVING)
     {
         KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
-        m_hotItem = -1;
-        m_menuBand->_OnHotItemChanged(NULL, -1);
-        m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+
+        if (m_menuBand->_OnHotItemChanged(NULL, -1) == S_FALSE)
+        {
+            *theResult = 1;
+            return S_OK;
+        }
+        else
+        {
+            m_hotItem = -1;
+            m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+            return S_OK;
+        }
     }
     else if (m_hotItem != hot->idNew)
     {
-        DWORD elapsed = 0;
-        SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
-        SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
+        if (hot->dwFlags & HICF_MOUSE &&
+            m_toolbarFlags & SMINIT_VERTICAL)
+        {
+            DWORD elapsed = 0;
+            SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
+            SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
+        }
 
         m_hotItem = hot->idNew;
         m_menuBand->_OnHotItemChanged(this, m_hotItem);
         m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+
+        if (m_isTracking && !(m_toolbarFlags & SMINIT_VERTICAL))
+        {
+            KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+
+            m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1);
+
+            if (HasSubMenu(m_hotItem) == S_OK)
+            {
+                PopupItem(m_hotItem);
+            }
+        }
+        return S_OK;
     }
     return S_OK;
 }
 
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu)
+HRESULT CMenuToolbarBase::OnHotItemChanged(CMenuToolbarBase * toolbar, INT item)
+{
+    BOOL wasChecked = FALSE;
+    if (m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL))
+    {
+        wasChecked = SendMessage(m_hwndToolbar, TB_ISBUTTONCHECKED, m_hotItem, 0);
+        if (wasChecked)
+        {
+            SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, FALSE);
+        }
+    }
+    m_hotBar = toolbar;
+    m_hotItem = item;
+    if (wasChecked && m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL))
+    {
+        SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, TRUE);
+    }
+    InvalidateDraw();
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item)
+{
+    if (toolbar == NULL && m_popupBar == this)
+    {
+        SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, FALSE);
+        m_isTracking = FALSE;
+    }
+    m_popupBar = toolbar;
+    m_popupItem = item;
+    InvalidateDraw();
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::IsTrackedItem(INT index)
+{
+    TBBUTTON btn;
+
+    if (m_hotBar != this)
+        return S_FALSE;
+
+    SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
+
+    if (m_hotItem == btn.idCommand)
+        return S_OK;
+    return S_FALSE;
+}
+
+HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index)
+{
+    TBBUTTON btn;
+    SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
+
+    if (m_hotItem != btn.idCommand)
+    {
+        SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
+    }
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* childShellMenu)
 {
     IBandSite* pBandSite;
     IDeskBar* pDeskBar;
 
     HRESULT hr = 0;
     RECT rc = { 0 };
+    RECT rcx = { 0 };
 
     if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
         return E_FAIL;
 
+    GetWindowRect(m_hwnd, &rcx);
+
     POINT a = { rc.left, rc.top };
     POINT b = { rc.right, rc.bottom };
+    POINT c = { rcx.left, rcx.top };
+    POINT d = { rcx.right, rcx.bottom };
 
     ClientToScreen(m_hwndToolbar, &a);
     ClientToScreen(m_hwndToolbar, &b);
+    ClientToScreen(m_hwnd, &c);
+    ClientToScreen(m_hwnd, &d);
 
-    POINTL pt = { b.x - 3, a.y - 3 };
-    RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar?
+    POINTL pt = { a.x, b.y };
+    RECTL rcl = { c.x, c.y, d.x, d.y };
+
+    if(m_toolbarFlags & SMINIT_VERTICAL)
+    {
+        pt.x = b.x - 3;
+        pt.y = a.y - 3;
+    }
 
 #if USE_SYSTEM_MENUSITE
     hr = CoCreateInstance(CLSID_MenuBandSite,
@@ -432,11 +588,11 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* chil
 #else
     hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
 #endif
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #if WRAP_MENUSITE
     hr = CMenuSite_Wrapper(pBandSite, IID_PPV_ARG(IBandSite, &pBandSite));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #endif
 
@@ -448,47 +604,69 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* chil
 #else
     hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
 #endif
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #if WRAP_MENUDESKBAR
     hr = CMenuDeskBar_Wrapper(pDeskBar, IID_PPV_ARG(IDeskBar, &pDeskBar));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #endif
 
     hr = pDeskBar->SetClient(pBandSite);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     hr = pBandSite->AddBand(childShellMenu);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     CComPtr<IMenuPopup> popup;
     hr = pDeskBar->QueryInterface(IID_PPV_ARG(IMenuPopup, &popup));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
-    m_popupItem = itemId;
-    m_menuBand->_OnPopupSubMenu(itemId, popup, &pt, &rcl);
+    m_isTracking = TRUE;
+    m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl, this, uItem);
 
     return S_OK;
 }
 
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, HMENU menu)
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu)
 {
     RECT rc = { 0 };
+    RECT rcx = { 0 };
 
     if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
         return E_FAIL;
 
+    GetClientRect(m_hwndToolbar, &rcx);
+
+    POINT a = { rc.left, rc.top };
     POINT b = { rc.right, rc.bottom };
+    POINT c = { rc.left, rc.top };
+    POINT d = { rc.right, rc.bottom };
 
+    ClientToScreen(m_hwndToolbar, &a);
     ClientToScreen(m_hwndToolbar, &b);
+    ClientToScreen(m_hwndToolbar, &c);
+    ClientToScreen(m_hwndToolbar, &d);
+
+    POINT pt = { a.x, b.y };
+    RECT rcl = { c.x, c.y, d.x, d.y };
+
+    if (m_toolbarFlags & SMINIT_VERTICAL)
+    {
+        pt.x = b.x;
+        pt.y = a.y;
+    }
 
     HMENU popup = GetSubMenu(menu, index);
 
-    m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, b.x, b.y);
+    m_isTracking = TRUE;
+    m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, pt.x, pt.y, rcl);
+
+    SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, FALSE);
+    m_isTracking = FALSE;
 
     return S_OK;
 }
@@ -502,7 +680,7 @@ HRESULT CMenuToolbarBase::DoContextMenu(IContextMenu* contextMenu)
         return E_FAIL;
 
     hr = contextMenu->QueryContextMenu(hPopup, 0, 0, UINT_MAX, CMF_NORMAL);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
     {
         DestroyMenu(hPopup);
         return hr;
@@ -532,7 +710,10 @@ HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theRe
         PopupItem(wParam);
         return S_FALSE;
     }
-    return m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
+    HRESULT hr = m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+    return S_OK; // filter out a possible S_FALSE from here.
 }
 
 HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType)
@@ -594,11 +775,9 @@ HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType)
 
             if (btn.dwData)
             {
-                m_hotItem = btn.idCommand;
-                if (prev != m_hotItem)
+                if (prev != btn.idCommand)
                 {
                     SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
-                    return m_menuBand->_OnHotItemChanged(this, m_hotItem);
                 }
                 return S_OK;
             }
@@ -614,32 +793,124 @@ HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType)
         }
     }
 
-    m_hotItem = -1;
-    if (prev != m_hotItem)
+    if (prev != -1)
     {
         SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0);
-        m_menuBand->_OnHotItemChanged(NULL, -1);
     }
     return S_FALSE;
 }
 
-BOOL
-AllocAndGetMenuString(HMENU hMenu, UINT ItemIDByPosition, WCHAR** String)
+HRESULT CMenuToolbarBase::AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSubMenu, INT iconId, DWORD_PTR buttonData, BOOL last)
+{
+    TBBUTTON tbb = { 0 };
+
+    tbb.fsState = TBSTATE_ENABLED;
+#if !USE_TBSTYLE_EX_VERTICAL
+    if (!last && (m_toolbarFlags & SMINIT_VERTICAL))
+        tbb.fsState |= TBSTATE_WRAP;
+#endif
+    tbb.fsStyle = 0;
+
+    if (hasSubMenu && (m_toolbarFlags & SMINIT_VERTICAL))
+        tbb.fsStyle |= BTNS_DROPDOWN;
+
+    if (!(m_toolbarFlags & SMINIT_VERTICAL))
+        tbb.fsStyle |= BTNS_AUTOSIZE | BTNS_CHECKGROUP;
+
+    tbb.iString = (INT_PTR) caption;
+    tbb.idCommand = commandId;
+
+    tbb.iBitmap = iconId;
+    tbb.dwData = buttonData;
+
+    if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb)))
+        return HRESULT_FROM_WIN32(GetLastError());
+
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::AddSeparator(BOOL last)
 {
-    int Length;
+    TBBUTTON tbb = { 0 };
+
+    tbb.fsState = TBSTATE_ENABLED;
+#if !USE_TBSTYLE_EX_VERTICAL
+    if (!last && (m_toolbarFlags & SMINIT_VERTICAL))
+        tbb.fsState |= TBSTATE_WRAP;
+#endif
+    tbb.fsStyle = BTNS_SEP;
+    tbb.iBitmap = 0;
+
+    if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb)))
+        return HRESULT_FROM_WIN32(GetLastError());
 
-    Length = GetMenuStringW(hMenu, ItemIDByPosition, NULL, 0, MF_BYPOSITION);
+    return S_OK;
+}
 
-    if (!Length)
-        return FALSE;
+HRESULT CMenuToolbarBase::AddPlaceholder()
+{
+    TBBUTTON tbb = { 0 };
+    PCWSTR MenuString = L"(Empty)";
 
-    /* Also allocate space for the terminating NULL character */
-    ++Length;
-    *String = (PWSTR) HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR));
+    tbb.fsState = 0;
+    tbb.fsStyle = 0;
+    tbb.iString = (INT_PTR) MenuString;
+    tbb.iBitmap = -1;
 
-    GetMenuStringW(hMenu, ItemIDByPosition, *String, Length, MF_BYPOSITION);
+    if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb)))
+        return HRESULT_FROM_WIN32(GetLastError());
 
-    return TRUE;
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData)
+{
+    TBBUTTONINFO info = { 0 };
+    info.cbSize = sizeof(TBBUTTONINFO);
+    info.dwMask = 0;
+    int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
+    if (index < 0)
+        return E_FAIL;
+
+    if (pIndex)
+        *pIndex = index;
+
+    if (pData)
+    {
+        TBBUTTON btn = { 0 };
+        if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
+            return E_FAIL;
+        *pData = btn.dwData;
+    }
+
+    return S_OK;
+}
+
+
+HRESULT CMenuToolbarBase::PopupItem(INT uItem)
+{
+    INT index;
+    DWORD_PTR dwData;
+
+    if (!(m_toolbarFlags & SMINIT_VERTICAL))
+    {
+        SendMessage(m_hwndToolbar, TB_SETHOTITEM, uItem, 0);
+        SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, TRUE);
+    }
+
+    GetDataFromId(uItem, &index, &dwData);
+
+    return InternalPopupItem(uItem, index, dwData);
+}
+
+HRESULT CMenuToolbarBase::HasSubMenu(INT uItem)
+{
+    INT index;
+    DWORD_PTR dwData;
+
+    GetDataFromId(uItem, &index, &dwData);
+
+    return InternalHasSubMenu(uItem, index, dwData);
 }
 
 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
@@ -649,13 +920,16 @@ CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
 }
 
 HRESULT  CMenuStaticToolbar::GetMenu(
-    HMENU *phmenu,
-    HWND *phwnd,
-    DWORD *pdwFlags)
+    _Out_opt_ HMENU *phmenu,
+    _Out_opt_ HWND *phwnd,
+    _Out_opt_ DWORD *pdwFlags)
 {
-    *phmenu = m_hmenu;
-    *phwnd = NULL;
-    *pdwFlags = m_dwMenuFlags;
+    if (phmenu)
+        *phmenu = m_hmenu;
+    if (phwnd)
+        *phwnd = NULL;
+    if (pdwFlags)
+        *pdwFlags = m_dwMenuFlags;
 
     return S_OK;
 }
@@ -671,54 +945,73 @@ HRESULT  CMenuStaticToolbar::SetMenu(
     return S_OK;
 }
 
-HRESULT CMenuStaticToolbar::FillToolbar()
+HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst)
 {
     int i;
     int ic = GetMenuItemCount(m_hmenu);
 
+    if (clearFirst)
+    {
+        while (SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0))
+        {
+            // empty;
+        }
+    }
+
+    int count = 0;
     for (i = 0; i < ic; i++)
     {
-        MENUITEMINFOW info;
-        TBBUTTON tbb = { 0 };
-        PWSTR MenuString = NULL;
+        BOOL last = i + 1 == ic;
 
-        tbb.fsState = TBSTATE_ENABLED;
-        tbb.fsStyle = 0;
+        MENUITEMINFOW info;
 
         info.cbSize = sizeof(info);
-        info.fMask = MIIM_FTYPE | MIIM_ID;
+        info.dwTypeData = NULL;
+        info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
 
-        GetMenuItemInfoW(m_hmenu, i, TRUE, &info);
+        if (!GetMenuItemInfoW(m_hmenu, i, TRUE, &info))
+        {
+            DbgPrint("Error obtaining info for menu item at pos=%d\n", i);
+            continue;
+        }
 
-        if (info.fType == MFT_STRING)
+        count++;
+
+        if (info.fType & MFT_SEPARATOR)
         {
-            if (!AllocAndGetMenuString(m_hmenu, i, &MenuString))
-                return E_OUTOFMEMORY;
-            if (::GetSubMenu(m_hmenu, i) != NULL)
-                tbb.fsStyle |= BTNS_DROPDOWN;
-            tbb.iString = (INT_PTR) MenuString;
-            tbb.idCommand = info.wID;
+            AddSeparator(last);
+        }
+        else if (!(info.fType & MFT_BITMAP))
+        {
+
+            info.cch++;
+            info.dwTypeData = (PWSTR) HeapAlloc(GetProcessHeap(), 0, (info.cch + 1) * sizeof(WCHAR));
+
+            info.fMask = MIIM_STRING | MIIM_SUBMENU | MIIM_ID;
+            GetMenuItemInfoW(m_hmenu, i, TRUE, &info);
 
             SMINFO * sminfo = new SMINFO();
             sminfo->dwMask = SMIM_ICON | SMIM_FLAGS;
-            if (SUCCEEDED(m_menuBand->_CallCBWithItemId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo))))
-            {
-                tbb.iBitmap = sminfo->iIcon;
-                tbb.dwData = reinterpret_cast<DWORD_PTR>(sminfo);
-                // FIXME: remove before deleting the toolbar or it will leak
-            }
-        }
-        else
-        {
-            tbb.fsStyle |= BTNS_SEP;
-        }
+            // FIXME: remove before deleting the toolbar or it will leak
 
-        SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+            HRESULT hr = m_menuBand->_CallCBWithItemId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo));
+            if (FAILED_UNEXPECTEDLY(hr))
+                return hr;
 
-        if (MenuString)
-            HeapFree(GetProcessHeap(), 0, MenuString);
+            AddButton(info.wID, info.dwTypeData, info.hSubMenu != NULL, sminfo->iIcon, reinterpret_cast<DWORD_PTR>(sminfo), last);
+
+            HeapFree(GetProcessHeap(), 0, info.dwTypeData);
+        }
     }
 
+    DbgPrint("Created toolbar with %d buttons.\n", count);
+
+    return S_OK;
+}
+
+HRESULT CMenuStaticToolbar::OnDeletingButton(const NMTOOLBAR * tb)
+{
+    delete reinterpret_cast<SMINFO*>(tb->tbButton.dwData);
     return S_OK;
 }
 
@@ -736,61 +1029,50 @@ HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *the
 {
     HRESULT hr;
     hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     // in case the clicked item has a submenu, we do not need to execute the item
     if (hr == S_FALSE)
+    {
+        DbgPrint("CMenuToolbarBase::OnCommand told us to cancel.\n");
         return hr;
+    }
 
     return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
 }
 
-HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
+HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
 {
-    TBBUTTONINFO info = { 0 };
-    info.cbSize = sizeof(TBBUTTONINFO);
-    info.dwMask = 0;
-    int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
-    if (index < 0)
-        return E_FAIL;
-
-    TBBUTTON btn = { 0 };
-    SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
-
-    SMINFO * nfo = reinterpret_cast<SMINFO*>(btn.dwData);
+    SMINFO * nfo = reinterpret_cast<SMINFO*>(dwData);
     if (!nfo)
         return E_FAIL;
 
     if (nfo->dwFlags&SMIF_TRACKPOPUP)
     {
-        return PopupSubMenu(index, m_hmenu);
+        return PopupSubMenu(uItem, index, m_hmenu);
     }
     else
     {
         CComPtr<IShellMenu> shellMenu;
         HRESULT hr = m_menuBand->_CallCBWithItemId(uItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu));
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         return PopupSubMenu(uItem, index, shellMenu);
     }
 }
 
-HRESULT CMenuStaticToolbar::HasSubMenu(UINT uItem)
+HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
 {
-    TBBUTTONINFO info = { 0 };
-    info.cbSize = sizeof(TBBUTTONINFO);
-    info.dwMask = 0;
-    int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
-    if (index < 0)
-        return E_FAIL;
     return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE;
 }
 
 CMenuSFToolbar::CMenuSFToolbar(CMenuBand * menuBand) :
     CMenuToolbarBase(menuBand, TRUE),
-    m_shellFolder(NULL)
+    m_shellFolder(NULL),
+    m_idList(NULL),
+    m_hKey(NULL)
 {
 }
 
@@ -798,7 +1080,7 @@ CMenuSFToolbar::~CMenuSFToolbar()
 {
 }
 
-HRESULT CMenuSFToolbar::FillToolbar()
+HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
 {
     HRESULT hr;
     int i = 0;
@@ -809,19 +1091,16 @@ HRESULT CMenuSFToolbar::FillToolbar()
 
     LPITEMIDLIST item = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(sizeof(ITEMIDLIST)));
     ULONG fetched;
-    while ((hr = eidl->Next(1, &item, &fetched)) == S_OK)
+    hr = eidl->Next(1, &item, &fetched);
+    while (SUCCEEDED(hr) && fetched > 0)
     {
         INT index = 0;
         INT indexOpen = 0;
 
-        TBBUTTON tbb = { 0 };
-        tbb.fsState = TBSTATE_ENABLED;
-        tbb.fsStyle = 0;
-
         STRRET sr = { STRRET_CSTR, { 0 } };
 
         hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         StrRetToStr(&sr, NULL, &MenuString);
@@ -833,46 +1112,39 @@ HRESULT CMenuSFToolbar::FillToolbar()
         SFGAOF attrs = SFGAO_FOLDER;
         hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
 
-        if (attrs & SFGAO_FOLDER)
-        {
-            tbb.fsStyle |= BTNS_DROPDOWN;
-        }
-
-        tbb.idCommand = ++i;
-        tbb.iString = (INT_PTR) MenuString;
-        tbb.iBitmap = index;
-        tbb.dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
+        DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
         // FIXME: remove before deleting the toolbar or it will leak
 
-        SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
-        CoTaskMemFree(MenuString);
+        // Fetch next item already, so we know if the current one is the last
+        hr = eidl->Next(1, &item, &fetched);
+
+        AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData, FAILED(hr) || fetched == 0);
 
+        CoTaskMemFree(MenuString);
     }
     CoTaskMemFree(item);
 
     // If no items were added, show the "empty" placeholder
     if (i == 0)
     {
-        TBBUTTON tbb = { 0 };
-        PCWSTR MenuString = L"(Empty)";
-
-        tbb.fsState = 0/*TBSTATE_DISABLED*/;
-        tbb.fsStyle = 0;
-        tbb.iString = (INT_PTR) MenuString;
-        tbb.iBitmap = -1;
-
-        SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
-
-        return S_OK;
+        return AddPlaceholder();
     }
 
+    DbgPrint("Created toolbar with %d buttons.\n", i);
+
     return hr;
 }
 
+HRESULT CMenuSFToolbar::OnDeletingButton(const NMTOOLBAR * tb)
+{
+    ILFree(reinterpret_cast<LPITEMIDLIST>(tb->tbButton.dwData));
+    return S_OK;
+}
+
 HRESULT CMenuSFToolbar::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
 {
     m_shellFolder = psf;
-    m_idList = pidlFolder;
+    m_idList = ILClone(pidlFolder);
     m_hKey = hKey;
     m_dwMenuFlags = dwFlags;
     return S_OK;
@@ -883,7 +1155,7 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
     HRESULT hr;
 
     hr = m_shellFolder->QueryInterface(riid, ppv);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (pdwFlags)
@@ -909,25 +1181,6 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
     return hr;
 }
 
-LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(UINT uItem, INT* pIndex)
-{
-    TBBUTTONINFO info = { 0 };
-    info.cbSize = sizeof(TBBUTTONINFO);
-    info.dwMask = 0;
-    int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
-    if (index < 0)
-        return NULL;
-
-    if (pIndex)
-        *pIndex = index;
-
-    TBBUTTON btn = { 0 };
-    if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
-        return NULL;
-
-    return reinterpret_cast<LPITEMIDLIST>(btn.dwData);
-}
-
 HRESULT CMenuSFToolbar::OnContextMenu(NMMOUSE * rclick)
 {
     HRESULT hr;
@@ -945,27 +1198,32 @@ HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResu
 {
     HRESULT hr;
     hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     // in case the clicked item has a submenu, we do not need to execute the item
     if (hr == S_FALSE)
+    {
+        DbgPrint("CMenuToolbarBase::OnCommand told us to cancel.\n");
         return hr;
+    }
+
+    DWORD_PTR data;
+    GetDataFromId(wParam, NULL, &data);
 
-    return m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
+    return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(data), SMC_SFEXEC, 0, 0);
 }
 
-HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
+HRESULT CMenuSFToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
 {
     HRESULT hr;
     UINT uId;
     UINT uIdAncestor;
     DWORD flags;
-    int index;
     CComPtr<IShellMenuCallback> psmc;
     CComPtr<IShellMenu> shellMenu;
 
-    LPITEMIDLIST pidl = GetPidlFromId(uItem, &index);
+    LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
 
     if (!pidl)
         return E_FAIL;
@@ -978,11 +1236,11 @@ HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
 #else
     hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &shellMenu));
 #endif
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #if WRAP_MENUBAND
     hr = CMenuBand_Wrapper(shellMenu, IID_PPV_ARG(IShellMenu, &shellMenu));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 #endif
 
@@ -990,29 +1248,29 @@ HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
 
     // FIXME: not sure what to use as uId/uIdAncestor here
     hr = shellMenu->Initialize(psmc, 0, uId, SMINIT_VERTICAL);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     CComPtr<IShellFolder> childFolder;
     hr = m_shellFolder->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &childFolder));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     hr = shellMenu->SetShellFolder(childFolder, NULL, NULL, 0);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     return PopupSubMenu(uItem, index, shellMenu);
 }
 
-HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
+HRESULT CMenuSFToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
 {
     HRESULT hr;
-    LPCITEMIDLIST pidl = GetPidlFromId(uItem);
+    LPCITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
 
     SFGAOF attrs = SFGAO_FOLDER;
     hr = m_shellFolder->GetAttributesOf(1, &pidl, &attrs);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     return (attrs & SFGAO_FOLDER) ? S_OK : S_FALSE;