[RSHELL]
[reactos.git] / base / shell / rshell / CMenuBand.cpp
index 7afd5f3..30703b5 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
 
+#undef UNIMPLEMENTED
+
+#define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
+
 extern "C"
-HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
+HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
 {
     *ppv = NULL;
 
@@ -40,7 +44,7 @@ HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
 
     HRESULT hr = site->QueryInterface(riid, ppv);
 
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         site->Release();
 
     return hr;
@@ -52,17 +56,15 @@ CMenuBand::CMenuBand() :
     m_site(NULL),
     m_psmc(NULL),
     m_subMenuChild(NULL),
+    m_hmenu(NULL),
+    m_menuOwner(NULL),
     m_useBigIcons(FALSE),
+    m_topLevelWindow(NULL),
     m_hotBar(NULL),
     m_hotItem(-1),
-    m_popupItem(-1)
+    m_trackingPopup(FALSE)
 {
     m_focusManager = CMenuFocusManager::AcquireManager();
-
-    m_marlett = CreateFont(
-        0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET,
-        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
-        DEFAULT_QUALITY, FF_DONTCARE, L"Marlett");
 }
 
 CMenuBand::~CMenuBand()
@@ -74,8 +76,6 @@ CMenuBand::~CMenuBand()
 
     if (m_SFToolbar)
         delete m_SFToolbar;
-
-    DeleteObject(m_marlett);
 }
 
 HRESULT STDMETHODCALLTYPE  CMenuBand::Initialize(
@@ -126,15 +126,20 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::SetMenu(
     HWND hwnd,
     DWORD dwFlags)
 {
+    DbgPrint("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu, hwnd, dwFlags);
+
+    BOOL created = FALSE;
+
     if (m_staticToolbar == NULL)
     {
         m_staticToolbar = new CMenuStaticToolbar(this);
+        created = true;
     }
     m_hmenu = hmenu;
-    m_menuOwner;
+    m_menuOwner = hwnd;
 
     HRESULT hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_site)
@@ -142,14 +147,21 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::SetMenu(
         HWND hwndParent;
 
         hr = m_site->GetWindow(&hwndParent);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
-        hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
-        if (FAILED(hr))
-            return hr;
+        if (created)
+        {
+            hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
+            if (FAILED_UNEXPECTEDLY(hr))
+                return hr;
 
-        hr = m_staticToolbar->FillToolbar();
+            hr = m_staticToolbar->FillToolbar();
+        }
+        else
+        {
+            hr = m_staticToolbar->FillToolbar(TRUE);
+        }
     }
 
     return hr;
@@ -178,11 +190,11 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::SetSite(IUnknown *pUnkSite)
 
     hwndParent = NULL;
     hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     hr = m_site->GetWindow(&hwndParent);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (!::IsWindow(hwndParent))
@@ -191,32 +203,32 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::SetSite(IUnknown *pUnkSite)
     if (m_staticToolbar != NULL)
     {
         hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         hr = m_staticToolbar->FillToolbar();
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
     }
 
     if (m_SFToolbar != NULL)
     {
         hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         hr = m_SFToolbar->FillToolbar();
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
     }
 
     hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent));
-    if (FAILED(hr))
+    if (hr != E_NOINTERFACE && FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     CComPtr<IOleWindow> pTopLevelWindow;
     hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     return pTopLevelWindow->GetWindow(&m_topLevelWindow);
@@ -250,12 +262,12 @@ HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
 
     if (m_staticToolbar != NULL)
         hr = m_staticToolbar->GetIdealSize(sizeStatic);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_SFToolbar != NULL)
         hr = m_SFToolbar->GetIdealSize(sizeShlFld);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_staticToolbar == NULL && m_SFToolbar == NULL)
@@ -297,17 +309,19 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::GetBandInfo(
 
     if (m_staticToolbar != NULL)
         hr = m_staticToolbar->GetIdealSize(sizeStatic);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_SFToolbar != NULL)
         hr = m_SFToolbar->GetIdealSize(sizeShlFld);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_staticToolbar == NULL && m_SFToolbar == NULL)
         return E_FAIL;
 
+    pdbi->ptMinSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
+    pdbi->ptMinSize.y = sizeStatic.cy + sizeShlFld.cy;
     pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
     pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
 
@@ -320,24 +334,26 @@ HRESULT STDMETHODCALLTYPE  CMenuBand::ShowDW(BOOL fShow)
 
     if (m_staticToolbar != NULL)
         hr = m_staticToolbar->ShowWindow(fShow);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
     if (m_SFToolbar != NULL)
         hr = m_SFToolbar->ShowWindow(fShow);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (fShow)
     {
         hr = _CallCB(SMC_INITMENU, 0, 0);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
     }
 
-    if (fShow)
-        hr = m_focusManager->PushMenu(this);
-    else
-        hr = m_focusManager->PopMenu(this);
+    {
+        if (fShow)
+            hr = m_focusManager->PushMenu(this);
+        else
+            hr = m_focusManager->PopMenu(this);
+    }
 
     return S_OK;
 }
@@ -370,19 +386,22 @@ HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
 {
     HRESULT hr;
 
-    hr = m_subMenuParent->SetSubMenu(this, fActivate);
-    if (FAILED(hr))
-        return hr;
+    if (m_subMenuParent)
+    {
+        hr = m_subMenuParent->SetSubMenu(this, fActivate);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+    }
 
     if (fActivate)
     {
         CComPtr<IOleWindow> pTopLevelWindow;
         hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
     }
     else
@@ -409,6 +428,8 @@ HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdI
         {
             return S_FALSE;
         }
+
+        return S_FALSE;
     }
 
     UNIMPLEMENTED;
@@ -436,18 +457,26 @@ HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
     switch (dwSelectType)
     {
     case MPOS_CHILDTRACKING:
+        if (!m_subMenuParent)
+            break;
         // TODO: Cancel timers?
         return m_subMenuParent->OnSelect(dwSelectType);
     case MPOS_SELECTLEFT:
         if (m_subMenuChild)
             m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+        if (!m_subMenuParent)
+            break;
         return m_subMenuParent->OnSelect(dwSelectType);
     case MPOS_SELECTRIGHT:
+        if (!m_subMenuParent)
+            break;
         return m_subMenuParent->OnSelect(dwSelectType);
     case MPOS_EXECUTE:
     case MPOS_FULLCANCEL:
         if (m_subMenuChild)
             m_subMenuChild->OnSelect(dwSelectType);
+        if (!m_subMenuParent)
+            break;
         return m_subMenuParent->OnSelect(dwSelectType);
     case MPOS_CANCELLEVEL:
         if (m_subMenuChild)
@@ -465,8 +494,17 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
 
 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
 {
-    UNIMPLEMENTED;
-    return S_OK;
+    if (m_subMenuChild)
+        m_subMenuChild = NULL;
+    if (!punkClient)
+    {
+        if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(NULL, -1);
+        if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(NULL, -1);
+        return S_OK;
+    }
+    HRESULT hr =  punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
+    m_trackingPopup = m_subMenuChild != NULL;
+    return hr;
 }
 
 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
@@ -505,7 +543,7 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMID
     }
 
     HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
     if (m_site)
@@ -513,11 +551,11 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMID
         HWND hwndParent;
 
         hr = m_site->GetWindow(&hwndParent);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
         hr = m_SFToolbar->FillToolbar();
@@ -553,184 +591,18 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlag
 
 HRESULT STDMETHODCALLTYPE CMenuBand::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;
-    BOOL useFlatMenus = FALSE;
-    COLORREF clrText;
-    COLORREF clrTextHighlight;
-
-
     *theResult = 0;
-    switch (uMsg)
-    {
-    case WM_COMMAND:
-
-        if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
-        {
-            return m_staticToolbar->OnCommand(wParam, lParam, theResult);
-        }
-
-        if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
-        {
-            return m_SFToolbar->OnCommand(wParam, lParam, theResult);
-        }
-
-        return S_OK;
-
-    case WM_NOTIFY:
-        hdr = reinterpret_cast<LPNMHDR>(lParam);
-        switch (hdr->code)
-        {
-        case PGN_CALCSIZE:
-            csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
-
-            if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                SIZE tbs;
-                m_staticToolbar->GetIdealSize(tbs);
-                if (csize->dwFlag == PGF_CALCHEIGHT)
-                {
-                    csize->iHeight = tbs.cy;
-                }
-                else if (csize->dwFlag == PGF_CALCWIDTH)
-                {
-                    csize->iHeight = tbs.cx;
-                }
-            }
-
-            if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                SIZE tbs;
-                m_SFToolbar->GetIdealSize(tbs);
-                if (csize->dwFlag == PGF_CALCHEIGHT)
-                {
-                    csize->iHeight = tbs.cy;
-                }
-                else if (csize->dwFlag == PGF_CALCWIDTH)
-                {
-                    csize->iHeight = tbs.cx;
-                }
-            }
-            return S_OK;
-
-        case TBN_DROPDOWN:
-
-            if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
-                return m_staticToolbar->OnCommand(wp, 0, theResult);
-            }
-
-            if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
-                return m_SFToolbar->OnCommand(wp, 0, theResult);
-            }
-
-            return S_OK;
-
-        case TBN_HOTITEMCHANGE:
-            hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
-
-            if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                return m_staticToolbar->OnHotItemChange(hot);
-            }
-
-            if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                return m_SFToolbar->OnHotItemChange(hot);
-            }
-
-            return S_OK;
-
-        case NM_RCLICK:
-            rclick = reinterpret_cast<LPNMMOUSE>(hdr);
-
-            if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                return m_staticToolbar->OnContextMenu(rclick);
-            }
-
-            if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
-            {
-                return m_SFToolbar->OnContextMenu(rclick);
-            }
-
-            return S_OK;
-
-        case NM_CUSTOMDRAW:
-            cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
-            switch (cdraw->nmcd.dwDrawStage)
-            {
-            case CDDS_PREPAINT:
-                *theResult = CDRF_NOTIFYITEMDRAW;
-                return S_OK;
-
-            case CDDS_ITEMPREPAINT:
-
-                SystemParametersInfo(SPI_GETFLATMENU, 0, &useFlatMenus, 0);
-
-                clrText = GetSysColor(COLOR_MENUTEXT);
-                clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
-
-                bgBrush = GetSysColorBrush(COLOR_MENU);
-                hotBrush = GetSysColorBrush(useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT);
-
-                rc = cdraw->nmcd.rc;
-                hdc = cdraw->nmcd.hdc;
-
-                if (((INT)cdraw->nmcd.dwItemSpec == m_hotItem ||
-                    (m_hotItem < 0 && (INT)cdraw->nmcd.dwItemSpec == m_popupItem)))
-                {
-                    cdraw->nmcd.uItemState = CDIS_HOT;
-                }
 
-                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;
-                }
-
-                *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only
-                return S_OK;
-
-            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);
-                    DrawTextEx(cdraw->nmcd.hdc, text, 1, &cdraw->nmcd.rc, DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE, NULL);
-                }
-                *theResult = TRUE;
-                return S_OK;
-            }
-            return S_OK;
-        }
-        return S_OK;
+    if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
+    {
+        return m_staticToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
     }
 
+    if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
+    {
+        return m_SFToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
+    }
+        
     return S_FALSE;
 }
 
@@ -784,9 +656,25 @@ HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPI
     return hr;
 }
 
-HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y)
+HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
 {
-    ::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL);
+    TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
+
+    UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
+
+    m_trackingPopup = TRUE;
+    m_focusManager->PushTrackedPopup(this, popup);
+    if (m_menuOwner)
+    {
+        ::TrackPopupMenuEx(popup, flags, x, y, m_menuOwner, &params);
+    }
+    else
+    {
+        ::TrackPopupMenuEx(popup, flags, x, y, m_topLevelWindow, &params);
+    }
+    m_trackingPopup = FALSE;
+    m_focusManager->PopTrackedPopup(this, popup);
+
     return S_OK;
 }
 
@@ -798,12 +686,14 @@ HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
 
 HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
 {
-    if (m_hotBar && m_hotBar != tb)
-        m_hotBar->ChangeHotItem(-1);
+    if (m_trackingPopup && id == -1)
+    {
+        return S_FALSE;
+    }
     m_hotBar = tb;
     m_hotItem = id;
-    if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
-    if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
+    if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id);
+    if (m_SFToolbar) m_SFToolbar->OnHotItemChanged(tb, id);
     return S_OK;
 }
 
@@ -811,7 +701,52 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
 {
     HRESULT hr;
 
-    if (changeType == VK_DOWN)
+    if (!(m_dwFlags & SMINIT_VERTICAL))
+    {
+        if (changeType == MPOS_SELECTRIGHT)
+        {
+            SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
+            if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
+            {
+                DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
+                return S_FALSE;
+            }
+            else if (m_staticToolbar && m_hotBar == m_staticToolbar)
+            {
+                hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
+                if (hr == S_FALSE)
+                {
+                    if (m_SFToolbar)
+                        return m_SFToolbar->ChangeHotItem(VK_HOME);
+                    else
+                        return m_staticToolbar->ChangeHotItem(VK_HOME);
+                }
+                return hr;
+            }
+        }
+        else if (changeType == MPOS_SELECTLEFT)
+        {
+            SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
+            if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
+            {
+                hr = m_staticToolbar->ChangeHotItem(VK_UP);
+                if (hr == S_FALSE)
+                {
+                    if (m_SFToolbar)
+                        return m_SFToolbar->ChangeHotItem(VK_END);
+                    else
+                        return m_staticToolbar->ChangeHotItem(VK_END);
+                }
+                return hr;
+            }
+            else if (m_SFToolbar && m_hotBar == m_SFToolbar)
+            {
+                DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
+                return S_FALSE;
+            }
+        }
+    }
+    else if (changeType == VK_DOWN)
     {
         if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
         {
@@ -869,6 +804,8 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
     {
         if (m_subMenuChild)
             m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+        if (!m_subMenuParent)
+            return S_OK;
         return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
     }
     else if (changeType == MPOS_SELECTRIGHT)
@@ -881,32 +818,48 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
                 return S_FALSE;
             }
         }
+        if (!m_subMenuParent)
+            return S_OK;
         return m_subMenuParent->OnSelect(changeType);
     }
     else
     {
+        if (!m_subMenuParent)
+            return S_OK;
         return m_subMenuParent->OnSelect(changeType);
     }
     return S_OK;
 }
 
-HRESULT CMenuBand::_OnPopupSubMenu(INT popupItem, IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
+HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude, CMenuToolbarBase * toolbar, INT item)
 {
     if (m_subMenuChild)
     {
         HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
-        if (FAILED(hr))
+        if (FAILED_UNEXPECTEDLY(hr))
             return hr;
     }
-    m_popupItem = popupItem;
-    m_subMenuChild = popup;
+    if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item);
+    if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item);
+    m_trackingPopup = popup != NULL;
     if (popup)
     {
-        IUnknown_SetSite(popup, m_subMenuParent);
+        if (m_subMenuParent)
+            IUnknown_SetSite(popup, m_subMenuParent);
+        else
+            IUnknown_SetSite(popup, m_site);
+
         popup->Popup(pAt, pExclude, MPPF_RIGHT);
     }
-    if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
-    if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
+    return S_OK;
+}
+
+HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable)
+{
+    if (m_staticToolbar)
+        m_staticToolbar->DisableMouseTrack(bDisable);
+    if (m_SFToolbar)
+        m_SFToolbar->DisableMouseTrack(bDisable);
     return S_OK;
 }