Author: dquintana Date: Wed Apr 2 17:37:37 2014 New Revision: 62601
URL: http://svn.reactos.org/svn/reactos?rev=62601&view=rev Log: [RSHELL] * Improvements on the focus manager. The menus work better, but still not fully. Commiting for backup/history purposes. CORE-7586
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.cpp branches/shell-experiments/base/shell/rshell/CMenuBand.h branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp branches/shell-experiments/base/shell/rshell/CMenuToolbars.h branches/shell-experiments/base/shell/rshell/precomp.h
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.cpp URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -65,7 +65,8 @@ 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 CMenuBand::_SetChildBand(CMenuBand * child) { m_childBand = child; + if (!child) + { + _ChangePopupItem(NULL, -1); + } return S_OK; }
@@ -524,13 +529,11 @@
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 @@
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 @@ } m_focusManager->PopTrackedPopup(popup);
- m_trackingPopup = FALSE; - DbgPrint("Tracking: %d\n", m_trackingPopup); + _DisableMouseTrack(FALSE);
return S_OK; } @@ -692,16 +693,36 @@ return S_OK; }
-HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id) -{ - if (m_trackingPopup && id == -1) - { +HRESULT CMenuBand::_ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags) +{ + 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 @@ } 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 @@ 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 @@ { 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 @@ { 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 @@ return S_OK; }
-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_UNEXPECTEDLY(hr)) - return hr; - } - - if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item); - if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item); - +HRESULT CMenuBand::_CancelCurrentPopup() +{ + if (!m_subMenuChild) + return S_FALSE; + + 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 (popup) - { - if (m_subMenuParent) - IUnknown_SetSite(popup, m_subMenuParent); - else - IUnknown_SetSite(popup, m_site); - - popup->Popup(pAt, pExclude, MPPF_RIGHT); - } + + if (m_subMenuParent) + IUnknown_SetSite(popup, m_subMenuParent); + else + IUnknown_SetSite(popup, m_site); + + popup->Popup(pAt, pExclude, MPPF_RIGHT);
return S_OK; } @@ -874,6 +889,20 @@ 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;
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.h URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -62,7 +62,8 @@
CMenuToolbarBase * m_hotBar; INT m_hotItem; - BOOL m_trackingPopup; + CMenuToolbarBase * m_popupBar; + INT m_popupItem;
public: CMenuBand(); @@ -176,13 +177,16 @@ 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() {
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -149,8 +149,6 @@ 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 @@ { 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 @@ entry.mb->_DisableMouseTrack(bDisable); } } - else - { - continue; - } + //else + //{ + // continue; + //} } m_mouseTrackDisabled = lastDisable; } @@ -220,20 +218,26 @@ } }
-HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd) -{ - int i = m_bandCount; - while (--i >= 0) +HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd, StackEntry ** pentry) +{ + 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 @@ 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) - { - HWND hwndToolbar = child; - if (SendMessage(hwndToolbar, WM_USER_ISTRACKEDITEM, iHitTestResult, 0)) - { - DbgPrint("Hot item tracking detected a change...\n"); + if (m_hwndUnderMouse != child) + { + 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 (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 @@ { BOOL callNext = TRUE; MSG* msg = reinterpret_cast<MSG*>(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 @@ { 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<MSG*>(lParam); + POINT pt = msg->pt;
switch (msg->message) { @@ -330,53 +362,17 @@ 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 @@ }
if (!callNext) - return 0; + return 1; }
return CallNextHookEx(m_hGetMsgHook, nCode, wParam, lParam); @@ -413,12 +409,12 @@
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 @@ 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 @@ 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);
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -58,6 +58,7 @@ private: StackEntry * m_current; StackEntry * m_parent; + StackEntry * m_menuBar;
HHOOK m_hMsgFilterHook; HHOOK m_hGetMsgHook; @@ -65,12 +66,11 @@
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 @@ -97,7 +97,7 @@ 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);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -37,20 +37,12 @@ // 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 @@ 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); - - 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<LPNMPGCALCSIZE>(hdr));
case TBN_DROPDOWN: return OnCommand(reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem, 0, theResult); @@ -95,12 +72,20 @@ case NM_CUSTOMDRAW: return OnCustomDraw(reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr), theResult);
+ case TBN_GETINFOTIP: + return OnGetInfoTip(reinterpret_cast<LPNMTBGETINFOTIP>(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 @@ 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,76 +110,159 @@ return S_FALSE; }
+LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CMenuToolbarBase * pthis = reinterpret_cast<CMenuToolbarBase *>(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + return pthis->SubclassProc(hWnd, uMsg, wParam, lParam); +} + +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_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: + OnPopupTimer(wParam); + } + + return m_SubclassOld(hWnd, uMsg, wParam, lParam); +} + +HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable) +{ + if (m_disableMouseTrack != bDisable) + { + m_disableMouseTrack = bDisable; + DbgPrint("DisableMouseTrack %d\n", bDisable); + } + return S_OK; +} + +HRESULT CMenuToolbarBase::OnPagerCalcSize(LPNMPGCALCSIZE csize) +{ + SIZE tbs; + GetIdealSize(tbs); + if (csize->dwFlag == PGF_CALCHEIGHT) + { + csize->iHeight = tbs.cy; + } + else if (csize->dwFlag == PGF_CALCWIDTH) + { + csize->iWidth = tbs.cx; + } + return S_OK; +} + HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult) { - RECT rc; - HDC hdc; - HBRUSH bgBrush; - HBRUSH hotBrush; + RECT rc; + HDC hdc; COLORREF clrText; - COLORREF clrTextHighlight; - bool isHot, isPopup; + HBRUSH bgBrush; + bool isHot, isPopup; TBBUTTONINFO btni;
switch (cdraw->nmcd.dwDrawStage) { case CDDS_PREPAINT: - if (m_toolbarFlags & SMINIT_VERTICAL) - *theResult = CDRF_NOTIFYITEMDRAW; + *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; + // 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) + { + // 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 { + // Remove HOT and CHECKED flags (will restore HOT if necessary) 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 + + // 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<LPARAM>(&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); - WCHAR text [] = L"8"; 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; @@ -212,6 +276,7 @@ m_useFlatMenus(FALSE), m_SubclassOld(NULL), m_disableMouseTrack(FALSE), + m_timerEnabled(FALSE), m_menuBand(menuBand), m_hwndToolbar(NULL), m_dwMenuFlags(0), @@ -229,15 +294,15 @@
CMenuToolbarBase::~CMenuToolbarBase() { + if (m_hwndToolbar && m_hwndToolbar != m_hwnd) + DestroyWindow(m_hwndToolbar); + + if (m_hwnd) + DestroyWindow(m_hwnd); + 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); @@ -247,8 +312,10 @@ { ::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; @@ -256,13 +323,15 @@
HRESULT CMenuToolbarBase::UpdateImageLists() { - if ((m_toolbarFlags & (SMINIT_TOPLEVEL | SMINIT_VERTICAL)) == SMINIT_TOPLEVEL) // not vertical. - { - /* Hide the placeholders for the button images */ + 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; }
+ // Assign the correct imagelist and padding based on the current icon size + int shiml; if (m_menuBand->UseBigIcons()) { @@ -277,24 +346,27 @@
IImageList * piml; HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml)); - if (SUCCEEDED(hr)) + if (FAILED_UNEXPECTEDLY(hr)) + { + SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0); + } + else { SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(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); + DestroyWindow(m_hwndToolbar); + + DestroyWindow(m_hwnd); + m_hwndToolbar = NULL; m_hwnd = NULL; + return S_OK; }
@@ -303,23 +375,26 @@ 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; + LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER | WS_EX_TOOLWINDOW;
if (dwFlags & SMINIT_VERTICAL) { + // Activate vertical semantics tbStyles |= CCS_VERT;
#if USE_TBSTYLE_EX_VERTICAL - // FIXME: Use when it works in ros (?) - tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW; + tbExStyles |= TBSTYLE_EX_VERTICAL; #endif }
- m_toolbarFlags = dwFlags; - + 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)) + if (!::GetClientRect(hwndParent, &rc) || + (rc.left == rc.right) || + (rc.top == rc.bottom)) { rc.left = 0; rc.top = 0; @@ -335,6 +410,7 @@ if (hwndToolbar == NULL) return E_FAIL;
+ // If needed, create the pager. if (m_usePager) { LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE; @@ -359,12 +435,14 @@ m_hwnd = hwndToolbar; }
- /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */ + // 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<LONG_PTR>(this)); m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
+ // Configure the image lists UpdateImageLists();
return S_OK; @@ -388,17 +466,30 @@
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); - if (m_toolbarFlags & SMINIT_VERTICAL) + + // 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; + + return S_OK; +} + +HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd) +{ + 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) @@ -411,132 +502,165 @@ return S_OK; }
-LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CMenuToolbarBase * pthis = reinterpret_cast<CMenuToolbarBase *>(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - return pthis->SubclassProc(hWnd, uMsg, wParam, lParam); -} - -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_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); - - DbgPrint("Closing previous submenu...\n"); - - m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL, NULL, -1); - - DbgPrint("Opening new submenu...\n"); - - PopupItem(m_hotItem); - } - } - - return m_SubclassOld(hWnd, uMsg, wParam, lParam); +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) + { + 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) { - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); - - if (m_menuBand->_OnHotItemChanged(NULL, -1) == S_FALSE) - { - *theResult = 1; - } - else - { - m_menuBand->_OnHotItemChanged(NULL, -1); - m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING); - } - - return S_OK; - } - - if (m_hotItem != hot->idNew) - { - 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_menuBand->_OnHotItemChanged(this, hot->idNew); - 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); - - PopupItem(m_hotItem); - } - return S_OK; - } - - return S_OK; -} - -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); - } - } + // Only notify of LEAVING if this was the hot toolbar. + if (m_hotBar == this) + { + 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)) - { - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_hotItem, TRUE); - } + + if (m_hotBar == this) + { + 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<LPARAM>(&info)); + + SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); + } + } + InvalidateDraw(); return S_OK; }
-HRESULT CMenuToolbarBase::OnPopupItemChanged(CMenuToolbarBase * toolbar, INT item) -{ - if (toolbar == NULL && m_popupBar == this) +HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item) +{ + 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 @@ if (m_hotBar != this) return S_FALSE;
- SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)); + if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&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<LPARAM>(&btn)); + if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&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); - } - - return S_OK; -} - -HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, IShellMenu* childShellMenu) + m_isTracking = TRUE; + m_menuBand->_ChangeHotItem(this, btn.idCommand, HICF_MOUSE); + + return S_OK; +} + +HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* childShellMenu) { IBandSite* pBandSite; IDeskBar* pDeskBar; @@ -600,7 +724,7 @@ 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 @@ return hr;
m_isTracking = TRUE; - DbgPrint("%s -- Is Tracking: %d\n", __FUNCTION__, m_isTracking); - - m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl, this, uItem); - - return S_OK; -} - -HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, UINT index, HMENU menu) + + m_menuBand->_ChangePopupItem(this, iItem); + m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl); + + return S_OK; +} + +HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu) { RECT rc = { 0 }; RECT rcx = { 0 }; @@ -682,7 +806,7 @@ 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 @@ 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::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult) { - theResult = 0; - - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + if (m_disableMouseTrack) + { + *theResult = 1; + DbgPrint("Item click prevented by DisableMouseTrack\n"); + return S_OK; + } + + *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 @@ 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 @@ { 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 @@
if (prev != -1) { + DbgPrint("Setting Hot item to null\n"); SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0); } return S_FALSE; @@ -840,16 +976,16 @@
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; - - if (hasSubMenu && (m_toolbarFlags & SMINIT_VERTICAL)) + tbb.fsStyle = BTNS_CHECKGROUP; + + 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 @@
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 @@ 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<LPARAM>(&info)); + int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, iItem, reinterpret_cast<LPARAM>(&info)); if (index < 0) return E_FAIL;
@@ -915,29 +1059,45 @@ 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) + return S_OK; +} + +HRESULT CMenuToolbarBase::CancelCurrentPopup() +{ + return m_menuBand->_CancelCurrentPopup(); +} + +HRESULT CMenuToolbarBase::PopupItem(INT iItem) { INT index; DWORD_PTR dwData;
- GetDataFromId(uItem, &index, &dwData); - - if (!(m_toolbarFlags & SMINIT_VERTICAL)) - { - SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, uItem, TRUE); - } - - HRESULT hr = InternalHasSubMenu(uItem, index, dwData); + if (iItem < 0) + return S_OK; + + if (m_popupBar == this && m_popupItem == iItem) + return S_OK; + + 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,9 +1191,14 @@ } }
- DbgPrint("Created toolbar with %d buttons.\n", count); - - return S_OK; + return S_OK; +} + +HRESULT CMenuStaticToolbar::GetInfoTip(LPWSTR pszText, INT cchTextMax, INT iItem, INT index, DWORD_PTR dwData) +{ + //SMINFO * info = reinterpret_cast<SMINFO*>(dwData); + UNIMPLEMENTED; + return E_NOTIMPL; }
HRESULT CMenuStaticToolbar::OnDeletingButton(const NMTOOLBAR * tb) @@ -1074,7 +1239,7 @@ 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<SMINFO*>(dwData); if (!nfo) @@ -1082,20 +1247,20 @@
if (nfo->dwFlags&SMIF_TRACKPOPUP) { - return PopupSubMenu(uItem, index, m_hmenu); + return PopupSubMenu(iItem, index, m_hmenu); } else { CComPtr<IShellMenu> shellMenu; - HRESULT hr = m_menuBand->_CallCBWithItemId(uItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu)); + HRESULT hr = m_menuBand->_CallCBWithItemId(iItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu)); if (FAILED_UNEXPECTEDLY(hr)) return hr;
- return PopupSubMenu(uItem, index, shellMenu); - } -} - -HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) + return PopupSubMenu(iItem, index, shellMenu); + } +} + +HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) { return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE; } @@ -1163,9 +1328,14 @@ 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<LPITEMIDLIST>(dwData); + UNIMPLEMENTED; + return E_NOTIMPL; }
HRESULT CMenuSFToolbar::OnDeletingButton(const NMTOOLBAR * tb) @@ -1247,7 +1417,7 @@ return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(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 @@ if (FAILED_UNEXPECTEDLY(hr)) return hr;
- return PopupSubMenu(uItem, index, shellMenu); -} - -HRESULT CMenuSFToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) + return PopupSubMenu(iItem, index, shellMenu); +} + +HRESULT CMenuSFToolbar::InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) { HRESULT hr; LPCITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.h URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -34,6 +34,7 @@ BOOL m_useFlatMenus; WNDPROC m_SubclassOld; BOOL m_disableMouseTrack; + BOOL m_timerEnabled;
protected: CMenuBand * m_menuBand; @@ -47,7 +48,7 @@ CMenuToolbarBase * m_popupBar; INT m_popupItem;
- DWORD m_toolbarFlags; + DWORD m_initFlags; BOOL m_isTracking;
private: @@ -65,14 +66,14 @@
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 @@ 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 @@ 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 @@ 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 @@ 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); };
Modified: branches/shell-experiments/base/shell/rshell/precomp.h URL: http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rsh... ============================================================================== --- branches/shell-experiments/base/shell/rshell/precomp.h [iso-8859-1] (original) +++ branches/shell-experiments/base/shell/rshell/precomp.h [iso-8859-1] Wed Apr 2 17:37:37 2014 @@ -72,7 +72,7 @@ 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);