diff --git a/base/shell/rshell/CMenuBand.cpp b/base/shell/rshell/CMenuBand.cpp index 88a53d489eb..f3cf5fbd174 100644 --- a/base/shell/rshell/CMenuBand.cpp +++ b/base/shell/rshell/CMenuBand.cpp @@ -1017,6 +1017,24 @@ HRESULT CMenuBand::_KillPopupTimers() return hr; } +HRESULT CMenuBand::_MenuBarMouseDown(HWND hwnd, INT item) +{ + if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK) + m_staticToolbar->MenuBarMouseDown(item); + if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK) + m_SFToolbar->MenuBarMouseDown(item); + return S_OK; +} + +HRESULT CMenuBand::_MenuBarMouseUp(HWND hwnd, INT item) +{ + if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK) + m_staticToolbar->MenuBarMouseUp(item); + if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK) + m_SFToolbar->MenuBarMouseUp(item); + return S_OK; +} + HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags) { UNIMPLEMENTED; diff --git a/base/shell/rshell/CMenuBand.h b/base/shell/rshell/CMenuBand.h index d4cde91a61f..5a1fd12f38b 100644 --- a/base/shell/rshell/CMenuBand.h +++ b/base/shell/rshell/CMenuBand.h @@ -191,6 +191,8 @@ public: HRESULT _IsPopup(); HRESULT _IsTracking(); HRESULT _KillPopupTimers(); + HRESULT _MenuBarMouseDown(HWND hwnd, INT item); + HRESULT _MenuBarMouseUp(HWND hwnd, INT item); BOOL UseBigIcons() { diff --git a/base/shell/rshell/CMenuFocusManager.cpp b/base/shell/rshell/CMenuFocusManager.cpp index ce3f2ed2789..a3286d00b72 100644 --- a/base/shell/rshell/CMenuFocusManager.cpp +++ b/base/shell/rshell/CMenuFocusManager.cpp @@ -160,6 +160,9 @@ CMenuFocusManager::CMenuFocusManager() : m_selectedMenu(NULL), m_selectedItem(0), m_selectedItemFlags(0), + m_isLButtonDown(FALSE), + m_movedSinceDown(FALSE), + m_windowAtDown(NULL), m_bandCount(0) { m_ptPrev.x = 0; @@ -302,12 +305,18 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg) if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry) return TRUE; + + m_movedSinceDown = TRUE; + m_ptPrev = pt; child = WindowFromPoint(pt); StackEntry * entry = NULL; - IsTrackedWindow(child, &entry); + if (IsTrackedWindow(child, &entry) == S_OK) + { + DbgPrint("MouseMove %d\n", m_isLButtonDown); + } BOOL isTracking = FALSE; if (entry) @@ -320,7 +329,7 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg) { TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd, cCapture); DisableMouseTrack(NULL, FALSE); - if (isTracking && iHitTestResult>=0 && m_current->type == TrackedMenuEntry) + if (isTracking && iHitTestResult >= 0 && m_current->type == TrackedMenuEntry) SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0); PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, MAKELPARAM(isTracking, TRUE)); if (m_current->type == TrackedMenuEntry) @@ -364,6 +373,94 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg) return TRUE; } +LRESULT CMenuFocusManager::ProcessMouseDown(MSG* msg) +{ + HWND child; + int iHitTestResult = -1; + + // Don't do anything if another window is capturing the mouse. + HWND cCapture = ::GetCapture(); + if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry) + return TRUE; + + + POINT pt = msg->pt; + + child = WindowFromPoint(pt); + + StackEntry * entry = NULL; + if (IsTrackedWindow(child, &entry) != S_OK) + return TRUE; + + DbgPrint("MouseDown %d\n", m_isLButtonDown); + + BOOL isTracking = FALSE; + if (entry) + { + ScreenToClient(child, &pt); + iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt); + isTracking = entry->mb->_IsTracking(); + + if (iHitTestResult >= 0) + { + DbgPrint("MouseDown send %d\n", iHitTestResult); + entry->mb->_MenuBarMouseDown(child, iHitTestResult); + } + } + + msg->message = WM_NULL; + + m_isLButtonDown = TRUE; + m_movedSinceDown = FALSE; + m_windowAtDown = child; + + DbgPrint("MouseDown end %d\n", m_isLButtonDown); + + return TRUE; +} + +LRESULT CMenuFocusManager::ProcessMouseUp(MSG* msg) +{ + HWND child; + int iHitTestResult = -1; + + // Don't do anything if another window is capturing the mouse. + HWND cCapture = ::GetCapture(); + if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry) + return TRUE; + + if (!m_isLButtonDown) + return TRUE; + + m_isLButtonDown = FALSE; + + POINT pt = msg->pt; + + child = WindowFromPoint(pt); + + StackEntry * entry = NULL; + if (IsTrackedWindow(child, &entry) != S_OK) + return TRUE; + + DbgPrint("MouseUp %d\n", m_isLButtonDown); + + BOOL isTracking = FALSE; + if (entry) + { + ScreenToClient(child, &pt); + iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt); + isTracking = entry->mb->_IsTracking(); + + if (iHitTestResult >= 0) + { + DbgPrint("MouseUp send %d\n", iHitTestResult); + entry->mb->_MenuBarMouseUp(child, iHitTestResult); + } + } + + return TRUE; +} + LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam) { if (nCode < 0) @@ -434,6 +531,7 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM ho LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam) { + BOOL isLButton = FALSE; if (nCode < 0) return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam); @@ -447,6 +545,9 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL { case WM_NCLBUTTONDOWN: case WM_LBUTTONDOWN: + isLButton = TRUE; + + // fallthrough; case WM_NCRBUTTONDOWN: case WM_RBUTTONDOWN: if (m_current->type == MenuPopupEntry) @@ -457,8 +558,18 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL { SetCapture(NULL); m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL); + break; } } + + if (isLButton) + { + ProcessMouseDown(msg); + } + break; + case WM_NCLBUTTONUP: + case WM_LBUTTONUP: + ProcessMouseUp(msg); break; case WM_MOUSEMOVE: callNext = ProcessMouseMove(msg); diff --git a/base/shell/rshell/CMenuFocusManager.h b/base/shell/rshell/CMenuFocusManager.h index 603f5d86821..213111b9670 100644 --- a/base/shell/rshell/CMenuFocusManager.h +++ b/base/shell/rshell/CMenuFocusManager.h @@ -77,6 +77,10 @@ private: INT m_selectedItem; DWORD m_selectedItemFlags; + BOOL m_isLButtonDown; + BOOL m_movedSinceDown; + HWND m_windowAtDown; + // TODO: make dynamic #define MAX_RECURSE 20 StackEntry m_bandStack[MAX_RECURSE]; @@ -109,6 +113,8 @@ private: void SetCapture(HWND child); LRESULT ProcessMouseMove(MSG* msg); + LRESULT ProcessMouseDown(MSG* msg); + LRESULT ProcessMouseUp(MSG* msg); public: HRESULT PushMenuBar(CMenuBand * mb); HRESULT PushMenuPopup(CMenuBand * mb); diff --git a/base/shell/rshell/CMenuToolbars.cpp b/base/shell/rshell/CMenuToolbars.cpp index 556b3176b1f..60ee65cca99 100644 --- a/base/shell/rshell/CMenuToolbars.cpp +++ b/base/shell/rshell/CMenuToolbars.cpp @@ -49,7 +49,8 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM switch (uMsg) { case WM_COMMAND: - return OnCommand(wParam, lParam, theResult); + //return OnCommand(wParam, lParam, theResult); + return S_OK; case WM_NOTIFY: hdr = reinterpret_cast(lParam); @@ -828,6 +829,30 @@ HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theRe return m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE); } +HRESULT CMenuToolbarBase::MenuBarMouseDown(INT item) +{ + LRESULT theResult; + TBBUTTON btn; + + if (m_initFlags & SMINIT_VERTICAL) + return S_OK; + + SendMessage(m_hwndToolbar, TB_GETBUTTON, item, reinterpret_cast(&btn)); + return OnCommand(btn.idCommand, 0, &theResult); +} + +HRESULT CMenuToolbarBase::MenuBarMouseUp(INT item) +{ + LRESULT theResult; + TBBUTTON btn; + + if (!(m_initFlags & SMINIT_VERTICAL)) + return S_OK; + + SendMessage(m_hwndToolbar, TB_GETBUTTON, item, reinterpret_cast(&btn)); + return OnCommand(btn.idCommand, 0, &theResult); +} + HRESULT CMenuToolbarBase::ExecuteItem(INT iItem) { this->m_menuBand->_KillPopupTimers(); diff --git a/base/shell/rshell/CMenuToolbars.h b/base/shell/rshell/CMenuToolbars.h index a44bb128e3a..87ef81749e6 100644 --- a/base/shell/rshell/CMenuToolbars.h +++ b/base/shell/rshell/CMenuToolbars.h @@ -97,6 +97,9 @@ public: HRESULT KillPopupTimer(); + HRESULT MenuBarMouseDown(INT item); + HRESULT MenuBarMouseUp(INT item); + protected: virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0;