[RSHELL]
[reactos.git] / base / shell / rshell / CMenuToolbars.cpp
index 61fa88a..967e9a8 100644 (file)
@@ -40,13 +40,154 @@ HRESULT WINAPI SHGetImageList(
 #define TIMERID_HOTTRACK 1
 #define SUBCLASS_ID_MENUBAND 1
 
+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;
+    bool isHot, isPopup;
+
+    *theResult = 0;
+    switch (uMsg)
+    {
+    case WM_COMMAND:
+        return OnCommand(wParam, lParam, theResult);
+
+    case WM_NOTIFY:
+        hdr = reinterpret_cast<LPNMHDR>(lParam);
+        switch (hdr->code)
+        {
+        case PGN_CALCSIZE:
+            csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
+
+            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:
+            wParam = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
+            return OnCommand(wParam, 0, theResult);
+
+        case TBN_HOTITEMCHANGE:
+            hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
+            return OnHotItemChange(hot);
+
+        case NM_RCLICK:
+            rclick = reinterpret_cast<LPNMMOUSE>(hdr);
+
+            return OnContextMenu(rclick);
+
+        case NM_CUSTOMDRAW:
+            cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
+            switch (cdraw->nmcd.dwDrawStage)
+            {
+            case CDDS_PREPAINT:
+                *theResult = CDRF_NOTIFYITEMDRAW;
+                return S_OK;
+
+            case CDDS_ITEMPREPAINT:
+                
+                clrText = GetSysColor(COLOR_MENUTEXT);
+                clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
+
+                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;
+
+            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;
+        }
+        return S_OK;
+    }
+
+    return S_FALSE;
+}
+
 CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
     m_hwnd(NULL),
+    m_useFlatMenus(FALSE),
     m_menuBand(menuBand),
     m_hwndToolbar(NULL),
     m_dwMenuFlags(0),
-    m_hasIdealSize(FALSE)
+    m_SubclassOld(NULL),
+    m_hasIdealSize(FALSE),
+    m_usePager(usePager),
+    m_hotItem(-1),
+    m_popupItem(-1)
 {
+    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");
+}
+
+CMenuToolbarBase::~CMenuToolbarBase()
+{
+    DeleteObject(m_marlett);
 }
 
 HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd)
@@ -66,6 +207,8 @@ HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow)
 
     UpdateImageLists();
 
+    SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0);
+
     return S_OK;
 }
 
@@ -116,7 +259,9 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags)
     if (dwFlags & SMINIT_VERTICAL)
     {
         tbStyles |= CCS_VERT;
-        tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW;
+
+        // FIXME: Use when it works in ros (?)
+        //tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW;
     }
 
     RECT rc;
@@ -232,7 +377,7 @@ LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         {
             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)
             {
@@ -266,7 +411,23 @@ HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot)
     return S_OK;
 }
 
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu)
+HRESULT CMenuToolbarBase::OnHotItemChanged(CMenuToolbarBase * toolbar, INT item)
+{
+    m_hotBar = toolbar;
+    m_hotItem = item;
+    InvalidateDraw();
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item)
+{
+    m_popupBar = toolbar;
+    m_popupItem = item;
+    InvalidateDraw();
+    return S_OK;
+}
+
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* childShellMenu)
 {
     IBandSite* pBandSite;
     IDeskBar* pDeskBar;
@@ -283,10 +444,9 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* chil
     ClientToScreen(m_hwndToolbar, &a);
     ClientToScreen(m_hwndToolbar, &b);
 
-    POINTL pt = { b.x - 4, a.y };
+    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?
 
-
 #if USE_SYSTEM_MENUSITE
     hr = CoCreateInstance(CLSID_MenuBandSite,
         NULL,
@@ -332,7 +492,7 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* chil
     if (FAILED(hr))
         return hr;
 
-    m_menuBand->_OnPopupSubMenu(itemId, popup, &pt, &rcl);
+    m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl, this, m_popupItem);
 
     return S_OK;
 }
@@ -544,7 +704,7 @@ HRESULT CMenuStaticToolbar::FillToolbar()
         TBBUTTON tbb = { 0 };
         PWSTR MenuString = NULL;
 
-        tbb.fsState = TBSTATE_ENABLED;
+        tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
         tbb.fsStyle = 0;
 
         info.cbSize = sizeof(info);
@@ -608,7 +768,7 @@ HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *the
     return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
 }
 
-HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
+HRESULT CMenuStaticToolbar::PopupItem(INT uItem)
 {
     TBBUTTONINFO info = { 0 };
     info.cbSize = sizeof(TBBUTTONINFO);
@@ -639,7 +799,7 @@ HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
     }
 }
 
-HRESULT CMenuStaticToolbar::HasSubMenu(UINT uItem)
+HRESULT CMenuStaticToolbar::HasSubMenu(INT uItem)
 {
     TBBUTTONINFO info = { 0 };
     info.cbSize = sizeof(TBBUTTONINFO);
@@ -677,24 +837,25 @@ HRESULT CMenuSFToolbar::FillToolbar()
         INT indexOpen = 0;
 
         TBBUTTON tbb = { 0 };
-        tbb.fsState = TBSTATE_ENABLED;
+        tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
         tbb.fsStyle = 0;
 
-        CComPtr<IShellItem> psi;
-        hr = SHCreateShellItem(NULL, m_shellFolder, item, &psi);
-        if (FAILED(hr))
-            return hr;
+        STRRET sr = { STRRET_CSTR, { 0 } };
 
-        hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, &MenuString);
+        hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
         if (FAILED(hr))
             return hr;
 
+        StrRetToStr(&sr, NULL, &MenuString);
+
         index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
 
-        SFGAOF attrs;
-        hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
+        LPCITEMIDLIST itemc = item;
+
+        SFGAOF attrs = SFGAO_FOLDER;
+        hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
 
-        if (attrs != 0)
+        if (attrs & SFGAO_FOLDER)
         {
             tbb.fsStyle |= BTNS_DROPDOWN;
         }
@@ -706,7 +867,7 @@ HRESULT CMenuSFToolbar::FillToolbar()
         // FIXME: remove before deleting the toolbar or it will leak
 
         SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
-        HeapFree(GetProcessHeap(), 0, MenuString);
+        CoTaskMemFree(MenuString);
 
     }
     CoTaskMemFree(item);
@@ -770,7 +931,7 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
     return hr;
 }
 
-LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(UINT uItem, INT* pIndex)
+LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(INT uItem, INT* pIndex)
 {
     TBBUTTONINFO info = { 0 };
     info.cbSize = sizeof(TBBUTTONINFO);
@@ -816,7 +977,7 @@ HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResu
     return m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
 }
 
-HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
+HRESULT CMenuSFToolbar::PopupItem(INT uItem)
 {
     HRESULT hr;
     UINT uId;
@@ -866,18 +1027,15 @@ HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
     return PopupSubMenu(uItem, index, shellMenu);
 }
 
-HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
+HRESULT CMenuSFToolbar::HasSubMenu(INT uItem)
 {
     HRESULT hr;
-    CComPtr<IShellItem> psi;
-    hr = SHCreateShellItem(NULL, m_shellFolder, GetPidlFromId(uItem), &psi);
-    if (FAILED(hr))
-        return S_FALSE;
+    LPCITEMIDLIST pidl = GetPidlFromId(uItem);
 
-    SFGAOF attrs;
-    hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
+    SFGAOF attrs = SFGAO_FOLDER;
+    hr = m_shellFolder->GetAttributesOf(1, &pidl, &attrs);
     if (FAILED(hr))
         return hr;
 
-    return (attrs != 0) ? S_OK : S_FALSE;
+    return (attrs & SFGAO_FOLDER) ? S_OK : S_FALSE;
 }