From a875dbf31729a133dd8e5938580c2df00b9a89f3 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Wed, 2 Apr 2014 17:37:37 +0000 Subject: [PATCH] [RSHELL] * Improvements on the focus manager. The menus work better, but still not fully. Commiting for backup/history purposes. CORE-7586 svn path=/branches/shell-experiments/; revision=62601 --- base/shell/rshell/CMenuBand.cpp | 135 +-- base/shell/rshell/CMenuBand.h | 10 +- base/shell/rshell/CMenuFocusManager.cpp | 193 +++-- base/shell/rshell/CMenuFocusManager.h | 8 +- base/shell/rshell/CMenuToolbars.cpp | 1002 +++++++++++++---------- base/shell/rshell/CMenuToolbars.h | 37 +- base/shell/rshell/precomp.h | 2 +- 7 files changed, 810 insertions(+), 577 deletions(-) diff --git a/base/shell/rshell/CMenuBand.cpp b/base/shell/rshell/CMenuBand.cpp index 4374417e496..f3c007eb223 100644 --- a/base/shell/rshell/CMenuBand.cpp +++ b/base/shell/rshell/CMenuBand.cpp @@ -65,7 +65,8 @@ CMenuBand::CMenuBand() : m_topLevelWindow(NULL), m_hotBar(NULL), m_hotItem(-1), - m_trackingPopup(FALSE) + m_popupBar(NULL), + m_popupItem(-1) { m_focusManager = CMenuFocusManager::AcquireManager(); } @@ -504,6 +505,10 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet) HRESULT CMenuBand::_SetChildBand(CMenuBand * child) { m_childBand = child; + if (!child) + { + _ChangePopupItem(NULL, -1); + } return S_OK; } @@ -524,13 +529,11 @@ HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient) 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; - DbgPrint("Tracking: %d\n", m_trackingPopup); + return hr; } @@ -666,8 +669,7 @@ HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, R UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN; - m_trackingPopup = TRUE; - DbgPrint("Tracking: %d\n", m_trackingPopup); + //_DisableMouseTrack(TRUE); m_focusManager->PushTrackedPopup(popup); if (m_menuOwner) @@ -680,8 +682,7 @@ HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, R } m_focusManager->PopTrackedPopup(popup); - m_trackingPopup = FALSE; - DbgPrint("Tracking: %d\n", m_trackingPopup); + _DisableMouseTrack(FALSE); return S_OK; } @@ -692,16 +693,36 @@ HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel) return S_OK; } -HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id) +HRESULT CMenuBand::_ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags) { - if (m_trackingPopup && id == -1) - { + if (m_hotBar == tb && m_hotItem == id) return S_FALSE; - } + + DbgPrint("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, tb, id); + + if (m_hotBar != tb) + _KillPopupTimers(); + m_hotBar = tb; m_hotItem = id; - if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id); - if (m_SFToolbar) m_SFToolbar->OnHotItemChanged(tb, id); + if (m_staticToolbar) m_staticToolbar->ChangeHotItem(tb, id, dwFlags); + if (m_SFToolbar) m_SFToolbar->ChangeHotItem(tb, id, dwFlags); + + _MenuItemHotTrack(MPOS_CHILDTRACKING); + + + return S_OK; +} + +HRESULT CMenuBand::_ChangePopupItem(CMenuToolbarBase * tb, INT id) +{ + DbgPrint("Popup item changed from %p %p, to %p %p\n", m_popupBar, m_popupItem, tb, id); + + m_popupBar = tb; + m_popupItem = id; + if (m_staticToolbar) m_staticToolbar->ChangePopupItem(tb, id); + if (m_SFToolbar) m_SFToolbar->ChangePopupItem(tb, id); + return S_OK; } @@ -721,13 +742,13 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType) } else if (m_staticToolbar && m_hotBar == m_staticToolbar) { - hr = m_staticToolbar->ChangeHotItem(VK_DOWN); + hr = m_staticToolbar->KeyboardItemChange(VK_DOWN); if (hr == S_FALSE) { if (m_SFToolbar) - return m_SFToolbar->ChangeHotItem(VK_HOME); + return m_SFToolbar->KeyboardItemChange(VK_HOME); else - return m_staticToolbar->ChangeHotItem(VK_HOME); + return m_staticToolbar->KeyboardItemChange(VK_HOME); } return hr; } @@ -737,13 +758,13 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType) SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0); if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL)) { - hr = m_staticToolbar->ChangeHotItem(VK_UP); + hr = m_staticToolbar->KeyboardItemChange(VK_UP); if (hr == S_FALSE) { if (m_SFToolbar) - return m_SFToolbar->ChangeHotItem(VK_END); + return m_SFToolbar->KeyboardItemChange(VK_END); else - return m_staticToolbar->ChangeHotItem(VK_END); + return m_staticToolbar->KeyboardItemChange(VK_END); } return hr; } @@ -758,25 +779,25 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType) { if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL)) { - hr = m_SFToolbar->ChangeHotItem(VK_DOWN); + hr = m_SFToolbar->KeyboardItemChange(VK_DOWN); if (hr == S_FALSE) { if (m_staticToolbar) - return m_staticToolbar->ChangeHotItem(VK_HOME); + return m_staticToolbar->KeyboardItemChange(VK_HOME); else - return m_SFToolbar->ChangeHotItem(VK_HOME); + return m_SFToolbar->KeyboardItemChange(VK_HOME); } return hr; } else if (m_staticToolbar && m_hotBar == m_staticToolbar) { - hr = m_staticToolbar->ChangeHotItem(VK_DOWN); + hr = m_staticToolbar->KeyboardItemChange(VK_DOWN); if (hr == S_FALSE) { if (m_SFToolbar) - return m_SFToolbar->ChangeHotItem(VK_HOME); + return m_SFToolbar->KeyboardItemChange(VK_HOME); else - return m_staticToolbar->ChangeHotItem(VK_HOME); + return m_staticToolbar->KeyboardItemChange(VK_HOME); } return hr; } @@ -785,25 +806,25 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType) { if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL)) { - hr = m_staticToolbar->ChangeHotItem(VK_UP); + hr = m_staticToolbar->KeyboardItemChange(VK_UP); if (hr == S_FALSE) { if (m_SFToolbar) - return m_SFToolbar->ChangeHotItem(VK_END); + return m_SFToolbar->KeyboardItemChange(VK_END); else - return m_staticToolbar->ChangeHotItem(VK_END); + return m_staticToolbar->KeyboardItemChange(VK_END); } return hr; } else if (m_SFToolbar && m_hotBar == m_SFToolbar) { - hr = m_SFToolbar->ChangeHotItem(VK_UP); + hr = m_SFToolbar->KeyboardItemChange(VK_UP); if (hr == S_FALSE) { if (m_staticToolbar) - return m_staticToolbar->ChangeHotItem(VK_END); + return m_staticToolbar->KeyboardItemChange(VK_END); else - return m_SFToolbar->ChangeHotItem(VK_END); + return m_SFToolbar->KeyboardItemChange(VK_END); } return hr; } @@ -836,31 +857,25 @@ HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType) return S_OK; } -HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude, CMenuToolbarBase * toolbar, INT item) +HRESULT CMenuBand::_CancelCurrentPopup() { - if (m_subMenuChild) - { - HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - } + if (!m_subMenuChild) + return S_FALSE; - if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item); - if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item); + HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL); + return hr; +} +HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude) +{ m_subMenuChild = popup; - m_trackingPopup = popup != NULL; - DbgPrint("Tracking: %d\n", m_trackingPopup); + + if (m_subMenuParent) + IUnknown_SetSite(popup, m_subMenuParent); + else + IUnknown_SetSite(popup, m_site); - if (popup) - { - if (m_subMenuParent) - IUnknown_SetSite(popup, m_subMenuParent); - else - IUnknown_SetSite(popup, m_site); - - popup->Popup(pAt, pExclude, MPPF_RIGHT); - } + popup->Popup(pAt, pExclude, MPPF_RIGHT); return S_OK; } @@ -874,6 +889,20 @@ HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable) return S_OK; } +HRESULT CMenuBand::_KillPopupTimers() +{ + HRESULT hr = S_OK; + if (m_staticToolbar) + hr = m_staticToolbar->KillPopupTimer(); + if (FAILED(hr)) + return hr; + + if (m_SFToolbar) + hr = m_SFToolbar->KillPopupTimer(); + + return hr; +} + HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags) { UNIMPLEMENTED; diff --git a/base/shell/rshell/CMenuBand.h b/base/shell/rshell/CMenuBand.h index 1c3f9ee30ed..d982a5aea09 100644 --- a/base/shell/rshell/CMenuBand.h +++ b/base/shell/rshell/CMenuBand.h @@ -62,7 +62,8 @@ private: CMenuToolbarBase * m_hotBar; INT m_hotItem; - BOOL m_trackingPopup; + CMenuToolbarBase * m_popupBar; + INT m_popupItem; public: CMenuBand(); @@ -176,13 +177,16 @@ public: HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam); HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude); HRESULT _GetTopLevelWindow(HWND*topLevel); - HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id); + HRESULT _ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags); + HRESULT _ChangePopupItem(CMenuToolbarBase * tb, INT id); HRESULT _MenuItemHotTrack(DWORD changeType); - HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude, CMenuToolbarBase * toolbar, INT item); + HRESULT _CancelCurrentPopup(); + HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude); HRESULT _DisableMouseTrack(BOOL bDisable); HRESULT _SetChildBand(CMenuBand * child); HRESULT _SetParentBand(CMenuBand * parent); HRESULT _IsPopup(); + HRESULT _KillPopupTimers(); BOOL UseBigIcons() { diff --git a/base/shell/rshell/CMenuFocusManager.cpp b/base/shell/rshell/CMenuFocusManager.cpp index 78f7736e889..be7b6e796be 100644 --- a/base/shell/rshell/CMenuFocusManager.cpp +++ b/base/shell/rshell/CMenuFocusManager.cpp @@ -149,8 +149,6 @@ CMenuFocusManager::CMenuFocusManager() : m_hMsgFilterHook(NULL), m_hGetMsgHook(NULL), m_mouseTrackDisabled(FALSE), - m_lastMoveFlags(0), - m_lastMovePos(0), m_captureHwnd(0), m_bandCount(0) { @@ -173,7 +171,7 @@ void CMenuFocusManager::DisableMouseTrack(HWND parent, BOOL disableThis) { StackEntry& entry = m_bandStack[i]; - if (entry.type == MenuPopupEntry) + if (entry.type != TrackedMenuEntry) { HWND hwnd; HRESULT hr = entry.mb->_GetTopLevelWindow(&hwnd); @@ -192,10 +190,10 @@ void CMenuFocusManager::DisableMouseTrack(HWND parent, BOOL disableThis) entry.mb->_DisableMouseTrack(bDisable); } } - else - { - continue; - } + //else + //{ + // continue; + //} } m_mouseTrackDisabled = lastDisable; } @@ -220,20 +218,26 @@ void CMenuFocusManager::SetCapture(HWND child) } } -HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd) +HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd, StackEntry ** pentry) { - int i = m_bandCount; - while (--i >= 0) + if (pentry) + *pentry = NULL; + + for (int i = m_bandCount; --i >= 0;) { StackEntry& entry = m_bandStack[i]; - if (entry.type == MenuPopupEntry) + if (entry.type != TrackedMenuEntry) { HRESULT hr = entry.mb->IsWindowOwner(hWnd); if (FAILED_UNEXPECTEDLY(hr)) return hr; if (hr == S_OK) + { + if (pentry) + *pentry = &entry; return S_OK; + } } } @@ -243,43 +247,58 @@ HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd) LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg) { HWND child; - POINT pt; int iHitTestResult; - pt = msg->pt; + POINT pt2 = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) }; + ClientToScreen(msg->hwnd, &pt2); + + /* Don't do anything if the mouse has not been moved */ + POINT pt = msg->pt; + if (pt.x == m_ptPrev.x && pt.y == m_ptPrev.y) + return TRUE; + + m_ptPrev = pt; child = WindowFromPoint(pt); - if (!m_parent) - return TRUE; - - if (m_parent->mb->IsWindowOwner(child) != S_OK) - return TRUE; - - ScreenToClient(child, &msg->pt); - - /* Don't do anything if the mouse has not been moved */ - if (msg->pt.x == m_ptPrev.x && msg->pt.y == m_ptPrev.y) - return TRUE; - - m_ptPrev = msg->pt; - - iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &msg->pt); - - /* Make sure that iHitTestResult is one of the menu items and that it is not the current menu item */ - if (iHitTestResult >= 0) + if (m_hwndUnderMouse != child) { - HWND hwndToolbar = child; - if (SendMessage(hwndToolbar, WM_USER_ISTRACKEDITEM, iHitTestResult, 0)) + WCHAR cn[1024]; + GetClassName(child, cn, 1023); + DbgPrint("Mouse moved to %p (%S)\n", child, cn); + m_hwndUnderMouse = child; + } + + StackEntry * entry = NULL; + + if (IsTrackedWindow(child, &entry) == S_OK) + { + ScreenToClient(child, &pt); + iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt); + + if (iHitTestResult >= 0 && + SendMessage(child, WM_USER_ISTRACKEDITEM, iHitTestResult, 0) == S_FALSE) { - DbgPrint("Hot item tracking detected a change...\n"); + DbgPrint("Hot item tracking detected a change (capture=%p)...\n", m_captureHwnd); + DisableMouseTrack(NULL, FALSE); if (m_current->type == TrackedMenuEntry) - SendMessage(m_parent->hwnd, WM_CANCELMODE, 0, 0); - else - m_current->mb->_MenuItemHotTrack(MPOS_CANCELLEVEL); - PostMessage(hwndToolbar, WM_USER_CHANGETRACKEDITEM, iHitTestResult, iHitTestResult); + SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0); + PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, iHitTestResult); return FALSE; } + + if (m_current->type == MenuPopupEntry) + { + SetCapture(child); + ScreenToClient(child, &pt2); + SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x, pt2.y)); + } + } + + if (m_current->type == MenuPopupEntry) + { + HWND parent = GetAncestor(child, GA_ROOT); + DisableMouseTrack(parent, FALSE); } return TRUE; @@ -294,16 +313,30 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam { BOOL callNext = TRUE; MSG* msg = reinterpret_cast(lParam); - + switch (msg->message) { + case WM_NCLBUTTONDOWN: + case WM_LBUTTONDOWN: + if (m_menuBar) + { + POINT pt = msg->pt; + HWND child = WindowFromPoint(pt); + BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK; + if (hoveringMenuBar) + { + HWND parent = GetAncestor(child, GA_ROOT); + m_menuBar->mb->_DisableMouseTrack(TRUE); + } + } + break; case WM_MOUSEMOVE: callNext = ProcessMouseMove(msg); break; } if (!callNext) - return 0; + return 1; } return CallNextHookEx(m_hMsgFilterHook, nCode, wParam, lParam); @@ -313,13 +346,12 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam) { if (nCode < 0) return CallNextHookEx(m_hGetMsgHook, nCode, wParam, lParam); - - LPARAM pos = (LPARAM) GetMessagePos(); - + if (nCode == HC_ACTION) { BOOL callNext = TRUE; MSG* msg = reinterpret_cast(lParam); + POINT pt = msg->pt; switch (msg->message) { @@ -330,53 +362,17 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam) case WM_LBUTTONDOWN: if (m_current->type == MenuPopupEntry) { - POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) }; - HWND child = WindowFromPoint(pt); - HWND window = GetAncestor(child, GA_ROOT); - if (IsTrackedWindow(window) != S_OK) + if (IsTrackedWindow(child) != S_OK) { + SetCapture(NULL); m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL); } } break; case WM_MOUSEMOVE: - if ((m_parent && m_parent->type==MenuPopupEntry) || ProcessMouseMove(msg)) - { - if (m_current->type == MenuPopupEntry) - { - if (m_lastMoveFlags != wParam || m_lastMovePos != pos) - { - m_lastMoveFlags = wParam; - m_lastMovePos = pos; - - POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) }; - - HWND child = WindowFromPoint(pt); - HWND window = GetAncestor(child, GA_ROOT); - - if (m_parent && m_parent->mb->IsWindowOwner(child) == S_OK) - { - DisableMouseTrack(window, FALSE); - } - else if (IsTrackedWindow(child) == S_OK) - { - DisableMouseTrack(window, FALSE); - SetCapture(child); - } - else - { - DisableMouseTrack(NULL, FALSE); - SetCapture(NULL); - } - } - } - } - else - { - callNext = FALSE; - } + callNext = ProcessMouseMove(msg); break; case WM_SYSKEYDOWN: case WM_KEYDOWN: @@ -405,7 +401,7 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam) } if (!callNext) - return 0; + return 1; } return CallNextHookEx(m_hGetMsgHook, nCode, wParam, lParam); @@ -413,12 +409,12 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam) HRESULT CMenuFocusManager::PlaceHooks() { - if (m_current->hmenu) + if (m_current->type == TrackedMenuEntry) { DbgPrint("Entering MSGFILTER hook...\n"); m_hMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, s_MsgFilterHook, NULL, m_threadId); } - else + else if (m_current->type == MenuPopupEntry) { DbgPrint("Entering GETMESSAGE hook...\n"); m_hGetMsgHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId); @@ -468,9 +464,21 @@ HRESULT CMenuFocusManager::UpdateFocus() m_parent = NULL; } + if (m_bandCount >= 1 && m_bandStack[0].type == MenuBarEntry) + { + m_menuBar = &(m_bandStack[0]); + } + else + { + m_menuBar = NULL; + } + if (old && (!m_current || old->type != m_current->type)) { - DisableMouseTrack(NULL, FALSE); + if (m_current->type != TrackedMenuEntry) + { + DisableMouseTrack(m_current->hwnd, FALSE); + } hr = RemoveHooks(); if (FAILED_UNEXPECTEDLY(hr)) @@ -484,13 +492,22 @@ HRESULT CMenuFocusManager::UpdateFocus() return hr; } + if (m_parent) + { + DisableMouseTrack(m_parent->hwnd, TRUE); + } + if ((m_current && m_current->type == MenuPopupEntry) && (!m_parent || m_parent->type == MenuBarEntry)) { - DisableMouseTrack(m_current->hwnd, FALSE); - // When the mouse moves, it should set itself to the proper band SetCapture(m_current->hwnd); + + //// FIXME: Debugging code, probably not right + //POINT pt2; + //GetCursorPos(&pt2); + //ScreenToClient(m_current->hwnd, &pt2); + //SendMessage(m_current->hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt2.x, pt2.y)); } _ASSERT(!m_parent || m_parent->type != TrackedMenuEntry); diff --git a/base/shell/rshell/CMenuFocusManager.h b/base/shell/rshell/CMenuFocusManager.h index 9212cbadc94..88a40dc48b1 100644 --- a/base/shell/rshell/CMenuFocusManager.h +++ b/base/shell/rshell/CMenuFocusManager.h @@ -58,6 +58,7 @@ private: private: StackEntry * m_current; StackEntry * m_parent; + StackEntry * m_menuBar; HHOOK m_hMsgFilterHook; HHOOK m_hGetMsgHook; @@ -65,13 +66,12 @@ private: BOOL m_mouseTrackDisabled; - WPARAM m_lastMoveFlags; - LPARAM m_lastMovePos; - POINT m_ptPrev; HWND m_captureHwnd; + HWND m_hwndUnderMouse; + // TODO: make dynamic #define MAX_RECURSE 20 StackEntry m_bandStack[MAX_RECURSE]; @@ -97,7 +97,7 @@ private: HRESULT PlaceHooks(); HRESULT RemoveHooks(); HRESULT UpdateFocus(); - HRESULT IsTrackedWindow(HWND hWnd); + HRESULT IsTrackedWindow(HWND hWnd, StackEntry ** pentry = NULL); void DisableMouseTrack(HWND parent, BOOL disableThis); void SetCapture(HWND child); diff --git a/base/shell/rshell/CMenuToolbars.cpp b/base/shell/rshell/CMenuToolbars.cpp index 77739a968ac..e50aa357eb7 100644 --- a/base/shell/rshell/CMenuToolbars.cpp +++ b/base/shell/rshell/CMenuToolbars.cpp @@ -37,20 +37,12 @@ HRESULT WINAPI SHGetImageList( // FIXME: Enable if/when wine comctl supports this flag properly #define USE_TBSTYLE_EX_VERTICAL 0 +// User-defined timer ID used while hot-tracking around the menu #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) { NMHDR * hdr; - NMPGCALCSIZE* csize; - SIZE tbs; *theResult = 0; switch (uMsg) @@ -62,26 +54,11 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM hdr = reinterpret_cast(lParam); switch (hdr->code) { - case TTN_GETDISPINFOA: - case TTN_GETDISPINFOW: - return S_OK; - case TBN_DELETINGBUTTON: return OnDeletingButton(reinterpret_cast(hdr)); case PGN_CALCSIZE: - csize = reinterpret_cast(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; + return OnPagerCalcSize(reinterpret_cast(hdr)); case TBN_DROPDOWN: return OnCommand(reinterpret_cast(hdr)->iItem, 0, theResult); @@ -95,12 +72,20 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case NM_CUSTOMDRAW: return OnCustomDraw(reinterpret_cast(hdr), theResult); + case TBN_GETINFOTIP: + return OnGetInfoTip(reinterpret_cast(hdr)); + + // Silence unhandled items so that they don't print as unknown case RBN_CHILDSIZE: return S_OK; + case TTN_GETDISPINFO: + return S_OK; + case NM_RELEASEDCAPTURE: break; + case NM_CLICK: case NM_RDOWN: case NM_LDOWN: break; @@ -115,10 +100,6 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case NM_TOOLTIPSCREATED: break; - case TBN_GETINFOTIP: - // TODO: Get tooltip for item - break; - default: DbgPrint("WM_NOTIFY unknown code %d, %d\n", hdr->code, hdr->idFrom); return S_OK; @@ -129,288 +110,6 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM return S_FALSE; } -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.dwDrawStage) - { - case CDDS_PREPAINT: - if (m_toolbarFlags & SMINIT_VERTICAL) - *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(cdraw->nmcd.dwItemSpec); - isPopup = m_popupBar == this && m_popupItem == static_cast(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(m_hwndToolbar, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast(&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_isTracking(FALSE) -{ - 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) -{ - return (m_hwnd && m_hwnd == hwnd) || - (m_hwndToolbar && m_hwndToolbar == hwnd) ? S_OK : S_FALSE; -} - -void CMenuToolbarBase::InvalidateDraw() -{ - InvalidateRect(m_hwnd, NULL, FALSE); -} - -HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow) -{ - ::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE); - - UpdateImageLists(); - - SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0); - - return S_OK; -} - -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()) - { - shiml = SHIL_LARGE; - SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 0)); - } - else - { - shiml = SHIL_SMALL; - SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 4)); - } - - IImageList * piml; - HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml)); - if (SUCCEEDED(hr)) - { - SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast(piml)); - } - else - { - SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0); - } - return S_OK; -} - -HRESULT CMenuToolbarBase::Close() -{ - DestroyWindow(m_hwndToolbar); - if (m_hwndToolbar != m_hwnd) - DestroyWindow(m_hwnd); - m_hwndToolbar = NULL; - m_hwnd = NULL; - return S_OK; -} - -HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) -{ - LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | - TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE | - CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP; - LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER; - - 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)) - { - rc.left = 0; - rc.top = 0; - rc.right = 1; - rc.bottom = 1; - } - - HWND hwndToolbar = CreateWindowEx( - tbExStyles, TOOLBARCLASSNAMEW, NULL, - tbStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); - - if (hwndToolbar == NULL) - return E_FAIL; - - if (m_usePager) - { - LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE; - LONG pgExStyles = 0; - - HWND hwndPager = CreateWindowEx( - pgExStyles, WC_PAGESCROLLER, NULL, - pgStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); - - ::SetParent(hwndToolbar, hwndPager); - ::SetParent(hwndPager, hwndParent); - - SendMessage(hwndPager, PGM_SETCHILD, 0, reinterpret_cast(hwndToolbar)); - m_hwndToolbar = hwndToolbar; - m_hwnd = hwndPager; - } - else - { - ::SetParent(hwndToolbar, hwndParent); - m_hwndToolbar = hwndToolbar; - m_hwnd = hwndToolbar; - } - - /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */ - SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); - - SetWindowLongPtr(hwndToolbar, GWLP_USERDATA, reinterpret_cast(this)); - m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast(CMenuToolbarBase::s_SubclassProc)); - - UpdateImageLists(); - - return S_OK; -} - -HRESULT CMenuToolbarBase::GetIdealSize(SIZE& size) -{ - size.cx = size.cy = 0; - - if (m_hwndToolbar && !m_hasIdealSize) - { - SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0); - SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast(&m_idealSize)); - m_hasIdealSize = TRUE; - } - - size = m_idealSize; - - return S_OK; -} - -HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy) -{ - if (m_hwnd != m_hwndToolbar) - { - SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0); - } - SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0); - 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; -} - -HRESULT CMenuToolbarBase::GetWindow(HWND *phwnd) -{ - if (!phwnd) - return E_FAIL; - - *phwnd = m_hwnd; - - return S_OK; -} - LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMenuToolbarBase * pthis = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); @@ -437,106 +136,531 @@ LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR OnWinEvent(hWnd, uMsg, wParam, lParam, &lr); break; case WM_TIMER: - if (wParam == TIMERID_HOTTRACK) - { - KillTimer(hWnd, TIMERID_HOTTRACK); - - DbgPrint("Closing previous submenu...\n"); - - m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1); - - DbgPrint("Opening new submenu...\n"); - - PopupItem(m_hotItem); - } + OnPopupTimer(wParam); } return m_SubclassOld(hWnd, uMsg, wParam, lParam); } -HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult) +HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable) { - if (m_disableMouseTrack && hot->dwFlags & HICF_MOUSE) + if (m_disableMouseTrack != bDisable) { - *theResult = 1; - return S_OK; + m_disableMouseTrack = bDisable; + DbgPrint("DisableMouseTrack %d\n", bDisable); } + return S_OK; +} - if (hot->dwFlags & HICF_LEAVING) +HRESULT CMenuToolbarBase::OnPagerCalcSize(LPNMPGCALCSIZE csize) +{ + SIZE tbs; + GetIdealSize(tbs); + if (csize->dwFlag == PGF_CALCHEIGHT) { - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + csize->iHeight = tbs.cy; + } + else if (csize->dwFlag == PGF_CALCWIDTH) + { + csize->iWidth = tbs.cx; + } + return S_OK; +} - if (m_menuBand->_OnHotItemChanged(NULL, -1) == S_FALSE) +HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult) +{ + RECT rc; + HDC hdc; + COLORREF clrText; + HBRUSH bgBrush; + bool isHot, isPopup; + TBBUTTONINFO btni; + + switch (cdraw->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: + *theResult = CDRF_NOTIFYITEMDRAW; + return S_OK; + + case CDDS_ITEMPREPAINT: + + rc = cdraw->nmcd.rc; + hdc = cdraw->nmcd.hdc; + + // The item with an active submenu gets the CHECKED flag. + isHot = m_hotBar == this && cdraw->nmcd.dwItemSpec == m_hotItem; + isPopup = m_popupBar == this && cdraw->nmcd.dwItemSpec == m_popupItem; + + if (m_initFlags & SMINIT_VERTICAL) { - *theResult = 1; + // Remove HOT and CHECKED flags (will restore HOT if necessary) + cdraw->nmcd.uItemState &= ~(CDIS_HOT|CDIS_CHECKED); + + // Decide on the colors + if (isHot || (m_hotItem < 0 && isPopup)) + { + cdraw->nmcd.uItemState |= CDIS_HOT; + + clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); + bgBrush = GetSysColorBrush(m_useFlatMenus ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT); + } + else + { + clrText = GetSysColor(COLOR_MENUTEXT); + bgBrush = GetSysColorBrush(COLOR_MENU); + } + + // Paint the background color with the selected color + FillRect(hdc, &rc, bgBrush); + + // Set the text color in advance, this color will be assigned when the ITEMPOSTPAINT triggers + SetTextColor(hdc, clrText); + + // Set the text color, will be used by the internal drawing code + cdraw->clrText = clrText; + cdraw->iListGap += 4; + + // Tell the default drawing code we don't want any fanciness, not even a background. + *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, useful for debugging only } else { - m_menuBand->_OnHotItemChanged(NULL, -1); - m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING); + // Remove HOT and CHECKED flags (will restore HOT if necessary) + cdraw->nmcd.uItemState &= ~CDIS_HOT; + + // Decide on the colors + if (isHot || (m_hotItem < 0 && isPopup)) + { + cdraw->nmcd.uItemState |= CDIS_HOT; + } + + *theResult = 0; } return S_OK; + + case CDDS_ITEMPOSTPAINT: + + // Fetch the button style + btni.cbSize = sizeof(btni); + btni.dwMask = TBIF_STYLE; + SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast(&btni)); + + // Check if we need to draw a submenu arrow + if (btni.fsStyle & BTNS_DROPDOWN) + { + // 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"; + + // 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); + + // Tweak the alignment by 1 pixel so the menu draws like the Windows start menu. + RECT rc = cdraw->nmcd.rc; + rc.right += 1; + + // The arrow is drawn at the right of the item's rect, aligned vertically. + 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_timerEnabled(FALSE), + m_menuBand(menuBand), + m_hwndToolbar(NULL), + m_dwMenuFlags(0), + m_hasIdealSize(FALSE), + m_usePager(usePager), + m_hotItem(-1), + m_popupItem(-1), + m_isTracking(FALSE) +{ + 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() +{ + if (m_hwndToolbar && m_hwndToolbar != m_hwnd) + DestroyWindow(m_hwndToolbar); + + if (m_hwnd) + DestroyWindow(m_hwnd); + + DeleteObject(m_marlett); +} + +void CMenuToolbarBase::InvalidateDraw() +{ + InvalidateRect(m_hwnd, NULL, FALSE); +} + +HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow) +{ + ::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE); + + // Ensure that the right image list is assigned to the toolbar + UpdateImageLists(); + + // For custom-drawing + SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0); + + return S_OK; +} + +HRESULT CMenuToolbarBase::UpdateImageLists() +{ + if ((m_initFlags & (SMINIT_TOPLEVEL | SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) // not vertical. + { + // No image list, prevents the buttons from having a margin at the left side + SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0); + return S_OK; } - if (m_hotItem != hot->idNew) + // Assign the correct imagelist and padding based on the current icon size + + int shiml; + if (m_menuBand->UseBigIcons()) { - 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); - } + shiml = SHIL_LARGE; + SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 0)); + } + else + { + shiml = SHIL_SMALL; + SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 4)); + } - m_menuBand->_OnHotItemChanged(this, hot->idNew); - m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING); + IImageList * piml; + HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml)); + if (FAILED_UNEXPECTEDLY(hr)) + { + SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0); + } + else + { + SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast(piml)); + } + return S_OK; +} - if (m_isTracking && !(m_toolbarFlags & SMINIT_VERTICAL)) - { - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); +HRESULT CMenuToolbarBase::Close() +{ + if (m_hwndToolbar != m_hwnd) + DestroyWindow(m_hwndToolbar); - m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1); + DestroyWindow(m_hwnd); - PopupItem(m_hotItem); - } - return S_OK; + m_hwndToolbar = NULL; + m_hwnd = NULL; + + return S_OK; +} + +HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) +{ + LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | + TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE | + CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP; + LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER | WS_EX_TOOLWINDOW; + + if (dwFlags & SMINIT_VERTICAL) + { + // Activate vertical semantics + tbStyles |= CCS_VERT; + +#if USE_TBSTYLE_EX_VERTICAL + tbExStyles |= TBSTYLE_EX_VERTICAL; +#endif + } + + m_initFlags = dwFlags; + + // Get a temporary rect to use while creating the toolbar window. + // Ensure that it is not a null rect. + RECT rc; + if (!::GetClientRect(hwndParent, &rc) || + (rc.left == rc.right) || + (rc.top == rc.bottom)) + { + rc.left = 0; + rc.top = 0; + rc.right = 1; + rc.bottom = 1; + } + + HWND hwndToolbar = CreateWindowEx( + tbExStyles, TOOLBARCLASSNAMEW, NULL, + tbStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, + hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); + + if (hwndToolbar == NULL) + return E_FAIL; + + // If needed, create the pager. + if (m_usePager) + { + LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE; + LONG pgExStyles = 0; + + HWND hwndPager = CreateWindowEx( + pgExStyles, WC_PAGESCROLLER, NULL, + pgStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, + hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); + + ::SetParent(hwndToolbar, hwndPager); + ::SetParent(hwndPager, hwndParent); + + SendMessage(hwndPager, PGM_SETCHILD, 0, reinterpret_cast(hwndToolbar)); + m_hwndToolbar = hwndToolbar; + m_hwnd = hwndPager; + } + else + { + ::SetParent(hwndToolbar, hwndParent); + m_hwndToolbar = hwndToolbar; + m_hwnd = hwndToolbar; + } + + // Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure. + SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + + // Apply subclassing + SetWindowLongPtr(hwndToolbar, GWLP_USERDATA, reinterpret_cast(this)); + m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast(CMenuToolbarBase::s_SubclassProc)); + + // Configure the image lists + UpdateImageLists(); + + return S_OK; +} + +HRESULT CMenuToolbarBase::GetIdealSize(SIZE& size) +{ + size.cx = size.cy = 0; + + if (m_hwndToolbar && !m_hasIdealSize) + { + SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0); + SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast(&m_idealSize)); + m_hasIdealSize = TRUE; + } + + size = m_idealSize; + + return S_OK; +} + +HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy) +{ + // If we have a pager, set the toolbar height to the ideal height of the toolbar + if (m_hwnd != m_hwndToolbar) + { + SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0); + } + + // Update the toolbar or pager to fit the requested rect + SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0); + + // In a vertical menu, resize the buttons to fit the width + if (m_initFlags & SMINIT_VERTICAL) + { + DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0); + SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize))); } return S_OK; } -HRESULT CMenuToolbarBase::OnHotItemChanged(CMenuToolbarBase * toolbar, INT item) +HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd) { - BOOL wasChecked = FALSE; - if (m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL)) + if (m_hwnd && m_hwnd == hwnd) return S_OK; + if (m_hwndToolbar && m_hwndToolbar == hwnd) return S_OK; + return S_FALSE; +} + +HRESULT CMenuToolbarBase::GetWindow(HWND *phwnd) +{ + if (!phwnd) + return E_FAIL; + + *phwnd = m_hwnd; + + return S_OK; +} + +HRESULT CMenuToolbarBase::OnGetInfoTip(NMTBGETINFOTIP * tip) +{ + INT index; + DWORD_PTR dwData; + + INT iItem = tip->iItem; + + GetDataFromId(iItem, &index, &dwData); + + return GetInfoTip(tip->pszText, tip->cchTextMax, iItem, index, dwData); +} + +HRESULT CMenuToolbarBase::OnPopupTimer(DWORD timerId) +{ + if (timerId != TIMERID_HOTTRACK) + return S_FALSE; + + KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + + if (!m_timerEnabled) + return S_FALSE; + + m_timerEnabled = FALSE; + + if (m_hotItem < 0) + return S_FALSE; + + // Returns S_FALSE if the current item did not show a submenu + HRESULT hr = PopupItem(m_hotItem); + if (hr != S_FALSE) + return hr; + + // If we didn't switch submenus, cancel the current popup regardless + if (m_popupBar) { - wasChecked = SendMessage(m_hwndToolbar, TB_ISBUTTONCHECKED, m_hotItem, 0); - if (wasChecked) + HRESULT hr = CancelCurrentPopup(); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + + return S_OK; +} + +HRESULT CMenuToolbarBase::KillPopupTimer() +{ + if (m_timerEnabled) + { + m_timerEnabled = FALSE; + KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + return S_OK; + } + return S_FALSE; +} + +HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult) +{ + // Prevent a change of hot item if the change was triggered by the mouse, + // and mouse tracking is disabled. + if (m_disableMouseTrack && hot->dwFlags & HICF_MOUSE) + { + *theResult = 1; + DbgPrint("Hot item change prevented by DisableMouseTrack\n"); + return S_OK; + } + + HRESULT hr = S_OK; + if (hot->dwFlags & HICF_LEAVING) + { + // Only notify of LEAVING if this was the hot toolbar. + if (m_hotBar == this) { - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, FALSE); + DbgPrint("The hot bar is now cold.\n"); + hr = m_menuBand->_ChangeHotItem(NULL, -1, hot->dwFlags); } } + else + { + hr = m_menuBand->_ChangeHotItem(this, hot->idNew, hot->dwFlags); + } + + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + // Reuse S_OK/S_FALSE as Continue/Cancel + *theResult = hr; + + return S_OK; +} + +HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD dwFlags) +{ + if (m_hotBar == toolbar && m_hotItem == item) + return S_FALSE; + + if (m_hotBar == this && toolbar != this) + { + SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0); + } + m_hotBar = toolbar; m_hotItem = item; - if (wasChecked && m_hotBar == this && !(m_toolbarFlags & SMINIT_VERTICAL)) + + if (m_hotBar == this) { - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, TRUE); + if (dwFlags & HICF_MOUSE) + { + // Vertical menus show/hide the submenu after a delay, + // but horizontal menubars switch between items instantly, + // if they were open. + 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_isTracking) + { + m_menuBand->_KillPopupTimers(); + + PopupItem(m_hotItem); + } + } + else + { + TBBUTTONINFO info; + info.cbSize = sizeof(info); + info.dwMask = 0; + + int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, item, reinterpret_cast(&info)); + + SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); + } } + InvalidateDraw(); return S_OK; } -HRESULT CMenuToolbarBase::OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item) +HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item) { - if (toolbar == NULL && m_popupBar == this) + if (m_popupBar == toolbar && m_popupItem == item) + return S_FALSE; + + if (m_popupBar == this && toolbar != this) { SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, FALSE); m_isTracking = FALSE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); } + m_popupBar = toolbar; m_popupItem = item; + + if (m_popupBar == this) + { + SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, TRUE); + } + InvalidateDraw(); return S_OK; } @@ -548,32 +672,32 @@ HRESULT CMenuToolbarBase::IsTrackedItem(INT index) if (m_hotBar != this) return S_FALSE; - SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn)); + if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn))) + return E_FAIL; if (m_hotItem == btn.idCommand) return S_OK; + + if (m_popupItem == btn.idCommand) + return S_OK; + return S_FALSE; } HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index) { TBBUTTON btn; - SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn)); + if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn))) + return E_FAIL; DbgPrint("Changing tracked item to %d...\n", index); - - if (m_hotItem != btn.idCommand) - { - m_isTracking = TRUE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); - - SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); - } + m_isTracking = TRUE; + m_menuBand->_ChangeHotItem(this, btn.idCommand, HICF_MOUSE); return S_OK; } -HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* childShellMenu) +HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* childShellMenu) { IBandSite* pBandSite; IDeskBar* pDeskBar; @@ -600,7 +724,7 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* child POINTL pt = { a.x, b.y }; RECTL rcl = { c.x, c.y, d.x, d.y }; - if (m_toolbarFlags & SMINIT_VERTICAL) + if (m_initFlags & SMINIT_VERTICAL) { pt.x = b.x - 3; pt.y = a.y - 3; @@ -652,14 +776,14 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* child return hr; m_isTracking = TRUE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); - m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl, this, uItem); + m_menuBand->_ChangePopupItem(this, iItem); + m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl); return S_OK; } -HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu) +HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu) { RECT rc = { 0 }; RECT rcx = { 0 }; @@ -682,7 +806,7 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu) POINT pt = { a.x, b.y }; RECT rcl = { c.x, c.y, d.x, d.y }; - if (m_toolbarFlags & SMINIT_VERTICAL) + if (m_initFlags & SMINIT_VERTICAL) { pt.x = b.x; pt.y = a.y; @@ -691,14 +815,12 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu) HMENU popup = GetSubMenu(menu, index); m_isTracking = TRUE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); + m_menuBand->_ChangePopupItem(this, iItem); m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, pt.x, pt.y, rcl); - - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, FALSE); + m_menuBand->_ChangePopupItem(NULL, -1); m_isTracking = FALSE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); return S_OK; } @@ -735,12 +857,24 @@ HRESULT CMenuToolbarBase::DoContextMenu(IContextMenu* contextMenu) HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult) { - theResult = 0; + if (m_disableMouseTrack) + { + *theResult = 1; + DbgPrint("Item click prevented by DisableMouseTrack\n"); + return S_OK; + } - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + *theResult = 0; + + m_menuBand->_KillPopupTimers(); if (PopupItem(wParam) == S_OK) + { + DbgPrint("PopupItem returned S_OK\n"); return S_FALSE; + } + + DbgPrint("Executing...\n"); HRESULT hr = m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE); @@ -750,7 +884,7 @@ HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theRe return S_OK; // filter out a possible S_FALSE from here. } -HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType) +HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType) { int prev = m_hotItem; int index = -1; @@ -811,6 +945,7 @@ HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType) { if (prev != btn.idCommand) { + DbgPrint("Setting Hot item to %d\n", index); SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); } return S_OK; @@ -829,6 +964,7 @@ HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType) if (prev != -1) { + DbgPrint("Setting Hot item to null\n"); SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0); } return S_FALSE; @@ -840,16 +976,16 @@ HRESULT CMenuToolbarBase::AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSu tbb.fsState = TBSTATE_ENABLED; #if !USE_TBSTYLE_EX_VERTICAL - if (!last && (m_toolbarFlags & SMINIT_VERTICAL)) + if (!last && (m_initFlags & SMINIT_VERTICAL)) tbb.fsState |= TBSTATE_WRAP; #endif - tbb.fsStyle = 0; + tbb.fsStyle = BTNS_CHECKGROUP; - if (hasSubMenu && (m_toolbarFlags & SMINIT_VERTICAL)) + if (hasSubMenu && (m_initFlags & SMINIT_VERTICAL)) tbb.fsStyle |= BTNS_DROPDOWN; - if (!(m_toolbarFlags & SMINIT_VERTICAL)) - tbb.fsStyle |= BTNS_AUTOSIZE | BTNS_CHECKGROUP; + if (!(m_initFlags & SMINIT_VERTICAL)) + tbb.fsStyle |= BTNS_AUTOSIZE; tbb.iString = (INT_PTR) caption; tbb.idCommand = commandId; @@ -869,7 +1005,7 @@ HRESULT CMenuToolbarBase::AddSeparator(BOOL last) tbb.fsState = TBSTATE_ENABLED; #if !USE_TBSTYLE_EX_VERTICAL - if (!last && (m_toolbarFlags & SMINIT_VERTICAL)) + if (!last && (m_initFlags & SMINIT_VERTICAL)) tbb.fsState |= TBSTATE_WRAP; #endif tbb.fsStyle = BTNS_SEP; @@ -897,15 +1033,23 @@ HRESULT CMenuToolbarBase::AddPlaceholder() return S_OK; } -HRESULT CMenuToolbarBase::GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData) +HRESULT CMenuToolbarBase::GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData) { + if (pData) + *pData = NULL; + + if (pIndex) + *pIndex = -1; + + if (iItem < 0) + return S_OK; + TBBUTTONINFO info = { 0 }; - DbgPrint("GetDataFromId %d\n", uItem); info.cbSize = sizeof(TBBUTTONINFO); info.dwMask = TBIF_COMMAND | TBIF_LPARAM; - int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast(&info)); + int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, iItem, reinterpret_cast(&info)); if (index < 0) return E_FAIL; @@ -915,29 +1059,45 @@ HRESULT CMenuToolbarBase::GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData if (pData) *pData = info.lParam; - DbgPrint("GetDataFromId ret: %d, %d, %x, %x\n", info.idCommand, index, info.lParam); - return S_OK; } -HRESULT CMenuToolbarBase::PopupItem(INT uItem) +HRESULT CMenuToolbarBase::CancelCurrentPopup() +{ + return m_menuBand->_CancelCurrentPopup(); +} + +HRESULT CMenuToolbarBase::PopupItem(INT iItem) { INT index; DWORD_PTR dwData; - GetDataFromId(uItem, &index, &dwData); + if (iItem < 0) + return S_OK; - if (!(m_toolbarFlags & SMINIT_VERTICAL)) - { - SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, TRUE); - } + if (m_popupBar == this && m_popupItem == iItem) + return S_OK; - HRESULT hr = InternalHasSubMenu(uItem, index, dwData); + GetDataFromId(iItem, &index, &dwData); + + HRESULT hr = InternalHasSubMenu(iItem, index, dwData); if (hr != S_OK) return hr; - return InternalPopupItem(uItem, index, dwData); + if (m_popupBar) + { + HRESULT hr = CancelCurrentPopup(); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + + if (!(m_initFlags & SMINIT_VERTICAL)) + { + DbgPrint("PopupItem non-vertical %d %d\n", index, iItem); + m_menuBand->_ChangeHotItem(this, iItem, 0); + } + + return InternalPopupItem(iItem, index, dwData); } CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) : @@ -1031,11 +1191,16 @@ HRESULT CMenuStaticToolbar::FillToolbar(BOOL clearFirst) } } - DbgPrint("Created toolbar with %d buttons.\n", count); - return S_OK; } +HRESULT CMenuStaticToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData) +{ + //SMINFO * info = reinterpret_cast(dwData); + UNIMPLEMENTED; + return E_NOTIMPL; +} + HRESULT CMenuStaticToolbar::OnDeletingButton(const NMTOOLBAR * tb) { delete reinterpret_cast(tb->tbButton.dwData); @@ -1074,7 +1239,7 @@ HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *the return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0); } -HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData) +HRESULT CMenuStaticToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData) { SMINFO * nfo = reinterpret_cast(dwData); if (!nfo) @@ -1082,20 +1247,20 @@ HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dw if (nfo->dwFlags&SMIF_TRACKPOPUP) { - return PopupSubMenu(uItem, index, m_hmenu); + return PopupSubMenu(iItem, index, m_hmenu); } else { CComPtr shellMenu; - HRESULT hr = m_menuBand->_CallCBWithItemId(uItem, SMC_GETOBJECT, reinterpret_cast(&IID_IShellMenu), reinterpret_cast(&shellMenu)); + HRESULT hr = m_menuBand->_CallCBWithItemId(iItem, SMC_GETOBJECT, reinterpret_cast(&IID_IShellMenu), reinterpret_cast(&shellMenu)); if (FAILED_UNEXPECTEDLY(hr)) return hr; - return PopupSubMenu(uItem, index, shellMenu); + return PopupSubMenu(iItem, index, shellMenu); } } -HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) +HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) { return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE; } @@ -1163,11 +1328,16 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst) return AddPlaceholder(); } - DbgPrint("Created toolbar with %d buttons.\n", i); - return hr; } +HRESULT CMenuSFToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData) +{ + //ITEMIDLIST * pidl = reinterpret_cast(dwData); + UNIMPLEMENTED; + return E_NOTIMPL; +} + HRESULT CMenuSFToolbar::OnDeletingButton(const NMTOOLBAR * tb) { ILFree(reinterpret_cast(tb->tbButton.dwData)); @@ -1247,7 +1417,7 @@ HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResu return m_menuBand->_CallCBWithItemPidl(reinterpret_cast(data), SMC_SFEXEC, 0, 0); } -HRESULT CMenuSFToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData) +HRESULT CMenuSFToolbar::InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData) { HRESULT hr; UINT uId; @@ -1293,10 +1463,10 @@ HRESULT CMenuSFToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData if (FAILED_UNEXPECTEDLY(hr)) return hr; - return PopupSubMenu(uItem, index, shellMenu); + return PopupSubMenu(iItem, index, shellMenu); } -HRESULT CMenuSFToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) +HRESULT CMenuSFToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) { HRESULT hr; LPCITEMIDLIST pidl = reinterpret_cast(dwData); diff --git a/base/shell/rshell/CMenuToolbars.h b/base/shell/rshell/CMenuToolbars.h index 971831ba052..598c85a519a 100644 --- a/base/shell/rshell/CMenuToolbars.h +++ b/base/shell/rshell/CMenuToolbars.h @@ -34,6 +34,7 @@ private: BOOL m_useFlatMenus; WNDPROC m_SubclassOld; BOOL m_disableMouseTrack; + BOOL m_timerEnabled; protected: CMenuBand * m_menuBand; @@ -47,7 +48,7 @@ protected: CMenuToolbarBase * m_popupBar; INT m_popupItem; - DWORD m_toolbarFlags; + DWORD m_initFlags; BOOL m_isTracking; private: @@ -65,14 +66,14 @@ public: HRESULT OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); - HRESULT OnHotItemChanged(CMenuToolbarBase * toolbar, INT item); - HRESULT OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item); + HRESULT ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD dwFlags); + HRESULT ChangePopupItem(CMenuToolbarBase * toolbar, INT item); HRESULT PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu); HRESULT PopupSubMenu(UINT itemId, UINT index, HMENU menu); HRESULT DoContextMenu(IContextMenu* contextMenu); - HRESULT ChangeHotItem(DWORD changeType); + HRESULT KeyboardItemChange(DWORD changeType); HRESULT OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult); HRESULT IsTrackedItem(INT index); @@ -88,15 +89,20 @@ public: virtual HRESULT FillToolbar(BOOL clearFirst=FALSE) = 0; virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0; - HRESULT PopupItem(INT uItem); - HRESULT GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData); + HRESULT CancelCurrentPopup(); + HRESULT PopupItem(INT iItem); + HRESULT GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData); + + HRESULT KillPopupTimer(); protected: virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult); virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0; - virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData) = 0; - virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) = 0; + virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData) = 0; + virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) = 0; + + virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData)=0; LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -107,7 +113,10 @@ protected: HRESULT UpdateImageLists(); private: + HRESULT OnPagerCalcSize(LPNMPGCALCSIZE csize); + HRESULT OnPopupTimer(DWORD timerId); HRESULT OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult); + HRESULT OnGetInfoTip(NMTBGETINFOTIP * tip); }; class CMenuStaticToolbar : @@ -130,8 +139,10 @@ public: protected: virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb); - virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData); - virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData); + virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData); + + virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData); + virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData); }; class CMenuSFToolbar : @@ -156,6 +167,8 @@ public: protected: virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb); - virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData); - virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData); + virtual HRESULT GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData); + + virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData); + virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData); }; diff --git a/base/shell/rshell/precomp.h b/base/shell/rshell/precomp.h index 06ee9bc4fa2..0eef2e0e113 100644 --- a/base/shell/rshell/precomp.h +++ b/base/shell/rshell/precomp.h @@ -72,7 +72,7 @@ Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...) else fname++; - szMsgStart = szMsg + sprintf(szMsg, "%s:%d: ", fname, line); + szMsgStart = szMsg + sprintf(szMsg, "[%10d] %s:%d: ", GetTickCount(), fname, line); va_start(vl, lpFormat); uRet = (ULONG) vsprintf(szMsgStart, lpFormat, vl);