From fd94119fa82e071658919193299352c236d1201d Mon Sep 17 00:00:00 2001 From: David Quintana Date: Sun, 29 Jun 2014 15:42:06 +0000 Subject: [PATCH] [RSHELL] * Change the way the menu items are activated. Now the menubar activates on mouse down, and the other items activate on mouse up. Not everything works perfectly yet, but it will eventually allow proper usage of the shell menus by keeping the mouse button down. I believe this is also the way to go to avoid the "instant reopening" of the menus when trying to close them. svn path=/branches/shell-experiments/; revision=63671 --- base/shell/rshell/CMenuBand.cpp | 18 ++++ base/shell/rshell/CMenuBand.h | 2 + base/shell/rshell/CMenuFocusManager.cpp | 115 +++++++++++++++++++++++- base/shell/rshell/CMenuFocusManager.h | 6 ++ base/shell/rshell/CMenuToolbars.cpp | 27 +++++- base/shell/rshell/CMenuToolbars.h | 3 + 6 files changed, 168 insertions(+), 3 deletions(-) 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;