From 4f5c5869053ad10b39477f3042c64f3694e2372b Mon Sep 17 00:00:00 2001 From: David Quintana Date: Tue, 11 Nov 2014 01:05:39 +0000 Subject: [PATCH] [RSHELL] * Make use of the CToolbar class here too. * Fix the menubar logic for closing menus on a second click. Almost. There's some glitch when clicking too fast, that I will fix later. svn path=/branches/shell-experiments/; revision=65373 --- base/shell/explorer-new/taskswnd.cpp | 12 +- base/shell/rshell/CMenuBand.cpp | 13 +- base/shell/rshell/CMenuBand.h | 1 + base/shell/rshell/CMenuFocusManager.cpp | 48 ++-- base/shell/rshell/CMenuToolbars.cpp | 291 +++++++++++------------- base/shell/rshell/CMenuToolbars.h | 33 +-- base/shell/rshell/precomp.h | 3 + include/reactos/rosctrls.h | 59 ++++- 8 files changed, 258 insertions(+), 202 deletions(-) diff --git a/base/shell/explorer-new/taskswnd.cpp b/base/shell/explorer-new/taskswnd.cpp index 52167bce786..d93bcdab9f3 100644 --- a/base/shell/explorer-new/taskswnd.cpp +++ b/base/shell/explorer-new/taskswnd.cpp @@ -27,10 +27,12 @@ /* Set DUMP_TASKS to 1 to enable a dump of the tasks and task groups every 5 seconds */ #define DUMP_TASKS 0 +#define DEBUG_SHELL_HOOK 0 const WCHAR szTaskSwitchWndClass [] = TEXT("MSTaskSwWClass"); const WCHAR szRunningApps [] = TEXT("Running Applications"); +#if DEBUG_SHELL_HOOK const struct { INT msg; LPCWSTR msg_name; @@ -51,6 +53,7 @@ const struct { { HSHELL_WINDOWREPLACING, L"HSHELL_WINDOWREPLACING" }, { HSHELL_RUDEAPPACTIVATED, L"HSHELL_RUDEAPPACTIVATED" }, }; +#endif typedef struct _TASK_GROUP { @@ -1445,6 +1448,7 @@ public: case HSHELL_GETMINRECT: default: { +#if DEBUG_SHELL_HOOK int i, found; for (i = 0, found = 0; i != sizeof(hshell_msg) / sizeof(hshell_msg[0]); i++) { @@ -1455,10 +1459,10 @@ public: break; } } - if (!found) - { - TRACE("Shell message %d unhandled (lParam = 0x%p)!\n", (INT) wParam, lParam); - } + if (found) + break; +#endif + TRACE("Shell message %d unhandled (lParam = 0x%p)!\n", (INT) wParam, lParam); break; } } diff --git a/base/shell/rshell/CMenuBand.cpp b/base/shell/rshell/CMenuBand.cpp index 29ba8a3c5ce..160df00eee9 100644 --- a/base/shell/rshell/CMenuBand.cpp +++ b/base/shell/rshell/CMenuBand.cpp @@ -389,14 +389,14 @@ HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow) if (m_staticToolbar != NULL) { - hr = m_staticToolbar->ShowWindow(fShow); + hr = m_staticToolbar->ShowDW(fShow); if (FAILED_UNEXPECTEDLY(hr)) return hr; } if (m_SFToolbar != NULL) { - hr = m_SFToolbar->ShowWindow(fShow); + hr = m_SFToolbar->ShowDW(fShow); if (FAILED_UNEXPECTEDLY(hr)) return hr; } @@ -1061,6 +1061,15 @@ HRESULT CMenuBand::_OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RE return S_OK; } +HRESULT CMenuBand::_BeforeCancelPopup() +{ + if (m_staticToolbar) + m_staticToolbar->BeforeCancelPopup(); + if (m_SFToolbar) + m_SFToolbar->BeforeCancelPopup(); + return S_OK; +} + HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable) { if (m_staticToolbar) diff --git a/base/shell/rshell/CMenuBand.h b/base/shell/rshell/CMenuBand.h index 3cb74f1b1ee..8d1d5b6f682 100644 --- a/base/shell/rshell/CMenuBand.h +++ b/base/shell/rshell/CMenuBand.h @@ -189,6 +189,7 @@ public: HRESULT _MenuItemHotTrack(DWORD changeType); HRESULT _CancelCurrentPopup(); HRESULT _OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL * pExclude, BOOL mouseInitiated); + HRESULT _BeforeCancelPopup(); HRESULT _DisableMouseTrack(BOOL bDisable); HRESULT _SetChildBand(CMenuBand * child); HRESULT _SetParentBand(CMenuBand * parent); diff --git a/base/shell/rshell/CMenuFocusManager.cpp b/base/shell/rshell/CMenuFocusManager.cpp index 36ef3d00418..0f76919ea54 100644 --- a/base/shell/rshell/CMenuFocusManager.cpp +++ b/base/shell/rshell/CMenuFocusManager.cpp @@ -383,8 +383,10 @@ LRESULT CMenuFocusManager::ProcessMouseDown(MSG* msg) // Don't do anything if another window is capturing the mouse. HWND cCapture = ::GetCapture(); if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry) + { + TRACE("Foreign capture active.\n"); return TRUE; - + } POINT pt = msg->pt; @@ -392,10 +394,22 @@ LRESULT CMenuFocusManager::ProcessMouseDown(MSG* msg) StackEntry * entry = NULL; if (IsTrackedWindow(child, &entry) != S_OK) + { + TRACE("Foreign window detected.\n"); return TRUE; + } TRACE("MouseDown %d\n", m_isLButtonDown); + if (entry->type == MenuBarEntry) + { + if (entry != m_current) + { + TRACE("Menubar with popup active.\n"); + return TRUE; + } + } + if (entry) { ScreenToClient(child, &pt); @@ -473,35 +487,19 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM ho switch (msg->message) { - case WM_NCLBUTTONDOWN: case WM_LBUTTONDOWN: - case WM_NCRBUTTONDOWN: case WM_RBUTTONDOWN: - if (m_menuBar) + if (m_menuBar && m_current->type == TrackedMenuEntry) { POINT pt = msg->pt; HWND child = WindowFromPoint(pt); BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK; if (hoveringMenuBar) { - m_menuBar->mb->_DisableMouseTrack(TRUE); - if (m_current->type == TrackedMenuEntry) - { - SendMessage(m_parent->hwnd, WM_CANCELMODE, 0, 0); - msg->message = WM_NULL; - } + m_menuBar->mb->_BeforeCancelPopup(); } } break; - case WM_NCLBUTTONUP: - case WM_LBUTTONUP: - case WM_NCRBUTTONUP: - case WM_RBUTTONUP: - if (m_current && m_current->type != TrackedMenuEntry) - { - msg->message = WM_NULL; - } - break; case WM_MOUSEMOVE: callNext = ProcessMouseMove(msg); break; @@ -564,6 +562,18 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL // fallthrough; case WM_NCRBUTTONDOWN: case WM_RBUTTONDOWN: + if (m_menuBar && m_current->type == MenuPopupEntry) + { + POINT pt = msg->pt; + HWND child = WindowFromPoint(pt); + BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK; + if (hoveringMenuBar) + { + m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL); + break; + } + } + if (m_current->type == MenuPopupEntry) { HWND child = WindowFromPoint(pt); diff --git a/base/shell/rshell/CMenuToolbars.cpp b/base/shell/rshell/CMenuToolbars.cpp index 32b17e9a346..3985ab60582 100644 --- a/base/shell/rshell/CMenuToolbars.cpp +++ b/base/shell/rshell/CMenuToolbars.cpp @@ -18,7 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "precomp.h" -#include #include #include #include @@ -26,6 +25,9 @@ #include "CMenuBand.h" #include "CMenuToolbars.h" +#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) + WINE_DEFAULT_DEBUG_CHANNEL(CMenuToolbars); extern "C" @@ -41,6 +43,13 @@ HRESULT WINAPI SHGetImageList( // User-defined timer ID used while hot-tracking around the menu #define TIMERID_HOTTRACK 1 +LRESULT CMenuToolbarBase::OnWinEventWrap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + LRESULT lr; + bHandled = OnWinEvent(m_hWnd, uMsg, wParam, lParam, &lr) != S_FALSE; + return lr; +} + HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) { NMHDR * hdr; @@ -116,38 +125,6 @@ HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM return S_FALSE; } -LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CMenuToolbarBase * pthis = reinterpret_cast(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, LOWORD(lParam), HIWORD(lParam)); - - 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) @@ -175,10 +152,6 @@ HRESULT CMenuToolbarBase::OnPagerCalcSize(LPNMPGCALCSIZE csize) HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult) { - RECT rc; - HDC hdc; - COLORREF clrText; - HBRUSH bgBrush; bool isHot, isPopup; TBBUTTONINFO btni; @@ -189,16 +162,18 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu 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 && (int) cdraw->nmcd.dwItemSpec == m_hotItem; isPopup = m_popupBar == this && (int) cdraw->nmcd.dwItemSpec == m_popupItem; if (m_initFlags & SMINIT_VERTICAL || IsAppThemed()) { + COLORREF clrText; + HBRUSH bgBrush; + RECT rc = cdraw->nmcd.rc; + HDC hdc = cdraw->nmcd.hdc; + // Remove HOT and CHECKED flags (will restore HOT if necessary) cdraw->nmcd.uItemState &= ~(CDIS_HOT | CDIS_CHECKED); @@ -250,7 +225,7 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu // Fetch the button style btni.cbSize = sizeof(btni); btni.dwMask = TBIF_STYLE; - SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast(&btni)); + GetButtonInfo(cdraw->nmcd.dwItemSpec, &btni); // Check if we need to draw a submenu arrow if (btni.fsStyle & BTNS_DROPDOWN) @@ -278,8 +253,7 @@ HRESULT CMenuToolbarBase::OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResu } CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) : - m_hwnd(NULL), - m_hwndToolbar(NULL), + m_pager(this, 1), m_useFlatMenus(FALSE), m_SubclassOld(NULL), m_disableMouseTrack(FALSE), @@ -288,9 +262,12 @@ CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) : m_dwMenuFlags(0), m_hasSizes(FALSE), m_usePager(usePager), + m_hotBar(NULL), m_hotItem(-1), + m_popupBar(NULL), m_popupItem(-1), - m_isTrackingPopup(FALSE) + m_isTrackingPopup(FALSE), + m_cancelingPopup(FALSE) { m_idealSize.cx = 0; m_idealSize.cy = 0; @@ -304,23 +281,23 @@ CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) : CMenuToolbarBase::~CMenuToolbarBase() { - if (m_hwndToolbar && m_hwndToolbar != m_hwnd) - DestroyWindow(m_hwndToolbar); + if (m_hWnd) + DestroyWindow(); - if (m_hwnd) - DestroyWindow(m_hwnd); + if (m_pager.m_hWnd) + m_pager.DestroyWindow(); DeleteObject(m_marlett); } void CMenuToolbarBase::InvalidateDraw() { - InvalidateRect(m_hwnd, NULL, FALSE); + InvalidateRect(NULL, FALSE); } -HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow) +HRESULT CMenuToolbarBase::ShowDW(BOOL fShow) { - ::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE); + ShowWindow(fShow ? SW_SHOW : SW_HIDE); // Ensure that the right image list is assigned to the toolbar UpdateImageLists(); @@ -336,7 +313,7 @@ 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); + SetImageList(NULL); return S_OK; } @@ -346,36 +323,34 @@ HRESULT CMenuToolbarBase::UpdateImageLists() if (m_menuBand->UseBigIcons()) { shiml = SHIL_LARGE; - SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 0)); + SetPadding(4, 0); } else { shiml = SHIL_SMALL; - SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 4)); + SetPadding(4, 4); } IImageList * piml; HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml)); if (FAILED_UNEXPECTEDLY(hr)) { - SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, 0); + SetImageList(NULL); } else { - SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast(piml)); + SetImageList((HIMAGELIST)piml); } return S_OK; } HRESULT CMenuToolbarBase::Close() { - if (m_hwndToolbar != m_hwnd) - DestroyWindow(m_hwndToolbar); + if (m_hWnd) + DestroyWindow(); - DestroyWindow(m_hwnd); - - m_hwndToolbar = NULL; - m_hwnd = NULL; + if (m_pager.m_hWnd) + m_pager.DestroyWindow(); return S_OK; } @@ -412,13 +387,7 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) 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; + SubclassWindow(Create(hwndParent, tbStyles, tbExStyles)); // If needed, create the pager. if (m_usePager) @@ -431,27 +400,13 @@ HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) pgStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); - ::SetParent(hwndToolbar, hwndPager); - ::SetParent(hwndPager, hwndParent); + m_pager.SubclassWindow(hwndPager); - SendMessage(hwndPager, PGM_SETCHILD, 0, reinterpret_cast(hwndToolbar)); - m_hwndToolbar = hwndToolbar; - m_hwnd = hwndPager; - } - else - { - ::SetParent(hwndToolbar, hwndParent); - m_hwndToolbar = hwndToolbar; - m_hwnd = hwndToolbar; + ::SetParent(m_hWnd, hwndPager); + + m_pager.SendMessageW(PGM_SETCHILD, 0, reinterpret_cast(m_hWnd)); } - // 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(); @@ -470,16 +425,16 @@ HRESULT CMenuToolbarBase::GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegr if (m_hasSizes) return S_OK; - if (!m_hwndToolbar) + if (!m_hWnd) return S_OK; // Obtain the ideal size, to be used as min and max - SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0); - SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast(&m_idealSize)); - SendMessageW(m_hwndToolbar, TB_GETIDEALSIZE, (m_initFlags & SMINIT_VERTICAL) != 0, reinterpret_cast(&m_idealSize)); + AutoSize(); + GetMaxSize(&m_idealSize); + GetIdealSize((m_initFlags & SMINIT_VERTICAL) != 0, &m_idealSize); // Obtain the button size, to be used as the integral size - DWORD size = SendMessageW(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0); + DWORD size = GetButtonSize(); m_itemSize.cx = GET_X_LPARAM(size); m_itemSize.cy = GET_Y_LPARAM(size); m_hasSizes = TRUE; @@ -496,20 +451,23 @@ HRESULT CMenuToolbarBase::GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegr HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy) { + // Update the toolbar or pager to fit the requested rect // If we have a pager, set the toolbar height to the ideal height of the toolbar - if (m_hwnd != m_hwndToolbar) + if (m_pager.m_hWnd) { - SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0); + SetWindowPos(NULL, x, y, cx, m_idealSize.cy, 0); + m_pager.SetWindowPos(NULL, x, y, cx, cy, 0); + } + else + { + SetWindowPos(NULL, x, y, cx, 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))); + DWORD btnSize = GetButtonSize(); + SetButtonSize(cx, GET_Y_LPARAM(btnSize)); } return S_OK; @@ -517,8 +475,8 @@ HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy) HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd) { - if (m_hwnd && m_hwnd == hwnd) return S_OK; - if (m_hwndToolbar && m_hwndToolbar == hwnd) return S_OK; + if (m_hWnd && m_hWnd == hwnd) return S_OK; + if (m_pager.m_hWnd && m_pager.m_hWnd == hwnd) return S_OK; return S_FALSE; } @@ -527,7 +485,10 @@ HRESULT CMenuToolbarBase::GetWindow(HWND *phwnd) if (!phwnd) return E_FAIL; - *phwnd = m_hwnd; + if (m_pager.m_hWnd) + *phwnd = m_pager.m_hWnd; + else + *phwnd = m_hWnd; return S_OK; } @@ -544,35 +505,38 @@ HRESULT CMenuToolbarBase::OnGetInfoTip(NMTBGETINFOTIP * tip) return InternalGetTooltip(iItem, index, dwData, tip->pszText, tip->cchTextMax); } -HRESULT CMenuToolbarBase::OnPopupTimer(DWORD timerId) +HRESULT CMenuToolbarBase::OnPopupTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - if (timerId != TIMERID_HOTTRACK) - return S_FALSE; + if (wParam != TIMERID_HOTTRACK) + { + bHandled = FALSE; + return 0; + } - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + KillTimer(TIMERID_HOTTRACK); if (!m_timerEnabled) - return S_FALSE; + return 0; m_timerEnabled = FALSE; if (m_hotItem < 0) - return S_FALSE; + return 0; // Returns S_FALSE if the current item did not show a submenu HRESULT hr = PopupItem(m_hotItem, FALSE); if (hr != S_FALSE) - return hr; + return 0; // If we didn't switch submenus, cancel the current popup regardless if (m_popupBar) { HRESULT hr = CancelCurrentPopup(); if (FAILED_UNEXPECTEDLY(hr)) - return hr; + return 0; } - return S_OK; + return 0; } HRESULT CMenuToolbarBase::KillPopupTimer() @@ -580,7 +544,7 @@ HRESULT CMenuToolbarBase::KillPopupTimer() if (m_timerEnabled) { m_timerEnabled = FALSE; - KillTimer(m_hwndToolbar, TIMERID_HOTTRACK); + KillTimer(TIMERID_HOTTRACK); return S_OK; } return S_FALSE; @@ -603,7 +567,7 @@ HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DW // Notify the toolbar if the hot-tracking left this toolbar if (m_hotBar == this && toolbar != this) { - SendMessage(m_hwndToolbar, TB_SETHOTITEM, (WPARAM) -1, 0); + SetHotItem(-1); } TRACE("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, toolbar, item); @@ -625,7 +589,7 @@ HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DW { DWORD elapsed = 0; SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0); - SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL); + SetTimer(TIMERID_HOTTRACK, elapsed); m_timerEnabled = TRUE; TRACE("SetTimer called with m_hotItem=%d\n", m_hotItem); } @@ -636,9 +600,9 @@ HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DW info.cbSize = sizeof(info); info.dwMask = 0; - int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, item, reinterpret_cast(&info)); + int index = GetButtonInfo(item, &info); - SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0); + SetHotItem(index); } } @@ -655,7 +619,7 @@ HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item) // Notify the toolbar if the popup-tracking this toolbar if (m_popupBar == this && toolbar != this) { - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, FALSE); + CheckButton(m_popupItem, FALSE); m_isTrackingPopup = FALSE; } @@ -664,24 +628,24 @@ HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item) if (m_popupBar == this) { - SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, TRUE); + CheckButton(m_popupItem, TRUE); } InvalidateDraw(); return S_OK; } -HRESULT CMenuToolbarBase::IsTrackedItem(INT index) +LRESULT CMenuToolbarBase::IsTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TBBUTTON btn; if (m_hotBar != this) return S_FALSE; - if (index < 0) + if (wParam < 0) return S_FALSE; - if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn))) + if (!GetButton(wParam, &btn)) return E_FAIL; if (m_hotItem == btn.idCommand) @@ -693,20 +657,23 @@ HRESULT CMenuToolbarBase::IsTrackedItem(INT index) return S_FALSE; } -HRESULT CMenuToolbarBase::ChangeTrackedItem(INT index, BOOL wasTracking, BOOL mouse) +LRESULT CMenuToolbarBase::ChangeTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { + BOOL wasTracking = LOWORD(lParam); + BOOL mouse = HIWORD(lParam); + TBBUTTON btn; - if (index < 0) + if (wParam < 0) { m_isTrackingPopup = FALSE; return m_menuBand->_ChangeHotItem(NULL, -1, HICF_MOUSE); } - if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn))) + if (!GetButton(wParam, &btn)) return E_FAIL; - TRACE("ChangeTrackedItem %d, %d\n", index, wasTracking); + TRACE("ChangeTrackedItem %d, %d\n", wParam, wasTracking); m_isTrackingPopup = wasTracking; return m_menuBand->_ChangeHotItem(this, btn.idCommand, mouse ? HICF_MOUSE : 0); } @@ -717,20 +684,22 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu* child RECT rc = { 0 }; RECT rcx = { 0 }; - if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast(&rc))) + if (!GetItemRect(index, &rc)) return E_FAIL; - GetWindowRect(m_hwnd, &rcx); + HWND topWnd; + GetWindow(&topWnd); + GetWindowRect(topWnd, &rcx); POINT a = { rc.left, rc.top }; POINT b = { rc.right, rc.bottom }; POINT c = { rcx.left, rcx.top }; POINT d = { rcx.right, rcx.bottom }; - ClientToScreen(m_hwndToolbar, &a); - ClientToScreen(m_hwndToolbar, &b); - ClientToScreen(m_hwnd, &c); - ClientToScreen(m_hwnd, &d); + ClientToScreen(m_hWnd, &a); + ClientToScreen(m_hWnd, &b); + ClientToScreen(topWnd, &c); + ClientToScreen(topWnd, &d); POINTL pt = { a.x, b.y }; RECTL rcl = { c.x, c.y, d.x, d.y }; @@ -755,14 +724,14 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu) // Calculate the submenu position and exclude area RECT rc = { 0 }; - if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast(&rc))) + if (!GetItemRect(index, &rc)) return E_FAIL; POINT a = { rc.left, rc.top }; POINT b = { rc.right, rc.bottom }; - ClientToScreen(m_hwndToolbar, &a); - ClientToScreen(m_hwndToolbar, &b); + ClientToScreen(m_hWnd, &a); + ClientToScreen(m_hWnd, &b); POINT pt = { a.x, b.y }; RECT rcl = { a.x, a.y, b.x, b.y }; @@ -782,8 +751,6 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu) m_menuBand->_ChangePopupItem(NULL, -1); m_isTrackingPopup = FALSE; - m_menuBand->_ChangeHotItem(NULL, -1, 0); - return S_OK; } @@ -798,6 +765,13 @@ HRESULT CMenuToolbarBase::TrackContextMenu(IContextMenu* contextMenu, POINT pt) return m_menuBand->_TrackContextMenu(contextMenu, pt.x, pt.y); } +HRESULT CMenuToolbarBase::BeforeCancelPopup() +{ + m_cancelingPopup = TRUE; + DbgPrint("BeforeCancelPopup\n"); + return S_OK; +} + HRESULT CMenuToolbarBase::ProcessClick(INT iItem) { if (m_disableMouseTrack) @@ -828,10 +802,15 @@ HRESULT CMenuToolbarBase::MenuBarMouseDown(INT iIndex) { TBBUTTON btn; - if (m_initFlags & SMINIT_VERTICAL) + if ((m_initFlags & SMINIT_VERTICAL) + || m_popupBar + || m_cancelingPopup) + { + m_cancelingPopup = FALSE; return S_OK; + } - ::SendMessageW(m_hwndToolbar, TB_GETBUTTON, iIndex, reinterpret_cast(&btn)); + GetButton(iIndex, &btn); return ProcessClick(btn.idCommand); } @@ -839,10 +818,12 @@ HRESULT CMenuToolbarBase::MenuBarMouseUp(INT iIndex) { TBBUTTON btn; + m_cancelingPopup = FALSE; + if (!(m_initFlags & SMINIT_VERTICAL)) return S_OK; - ::SendMessageW(m_hwndToolbar, TB_GETBUTTON, iIndex, reinterpret_cast(&btn)); + GetButton(iIndex, &btn); return ProcessClick(btn.idCommand); } @@ -877,7 +858,7 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType) if (dwSelectType != 0xFFFFFFFF) { - int count = SendMessage(m_hwndToolbar, TB_BUTTONCOUNT, 0, 0); + int count = GetButtonCount(); if (dwSelectType == VK_HOME) { @@ -896,7 +877,7 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType) TBBUTTONINFO info = { 0 }; info.cbSize = sizeof(TBBUTTONINFO); info.dwMask = 0; - index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, m_hotItem, reinterpret_cast(&info)); + index = GetButtonInfo(m_hotItem, &info); } if (index < 0) @@ -926,7 +907,7 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType) TBBUTTON btn = { 0 }; while (index >= 0 && index < count) { - DWORD res = SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast(&btn)); + DWORD res = GetButton(index, &btn); if (!res) return E_FAIL; @@ -939,8 +920,8 @@ HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType) { HWND tlw; m_menuBand->_GetTopLevelWindow(&tlw); - SendMessage(tlw, WM_CANCELMODE, 0, 0); - PostMessage(m_hwndToolbar, WM_USER_CHANGETRACKEDITEM, index, MAKELPARAM(m_isTrackingPopup, FALSE)); + SendMessageW(tlw, WM_CANCELMODE, 0, 0); + PostMessageW(m_hWnd, WM_USER_CHANGETRACKEDITEM, index, MAKELPARAM(m_isTrackingPopup, FALSE)); } else m_menuBand->_ChangeHotItem(this, btn.idCommand, 0); @@ -993,9 +974,10 @@ HRESULT CMenuToolbarBase::AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSu tbb.iBitmap = iconId; tbb.dwData = buttonData; - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) - return HRESULT_FROM_WIN32(GetLastError()); + m_hasSizes = FALSE; + if (!AddButtons(1, &tbb)) + return HRESULT_FROM_WIN32(GetLastError()); return S_OK; } @@ -1011,7 +993,9 @@ HRESULT CMenuToolbarBase::AddSeparator(BOOL last) tbb.fsStyle = BTNS_SEP; tbb.iBitmap = 0; - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) + m_hasSizes = FALSE; + + if (!AddButtons(1, &tbb)) return HRESULT_FROM_WIN32(GetLastError()); return S_OK; @@ -1020,14 +1004,16 @@ HRESULT CMenuToolbarBase::AddSeparator(BOOL last) HRESULT CMenuToolbarBase::AddPlaceholder() { TBBUTTON tbb = { 0 }; - PCWSTR MenuString = L"(Empty)"; + PCWSTR MenuString = L"(Empty)"; // FIXME: Make localizable tbb.fsState = 0; tbb.fsStyle = 0; tbb.iString = (INT_PTR) MenuString; tbb.iBitmap = -1; - if (!SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast(&tbb))) + m_hasSizes = FALSE; + + if (!AddButtons(1, &tbb)) return HRESULT_FROM_WIN32(GetLastError()); return S_OK; @@ -1035,10 +1021,11 @@ HRESULT CMenuToolbarBase::AddPlaceholder() HRESULT CMenuToolbarBase::ClearToolbar() { - while (SendMessage(m_hwndToolbar, TB_DELETEBUTTON, 0, 0)) + while (DeleteButton(0)) { // empty; } + m_hasSizes = FALSE; return S_OK; } @@ -1058,7 +1045,7 @@ HRESULT CMenuToolbarBase::GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData info.cbSize = sizeof(TBBUTTONINFO); info.dwMask = TBIF_COMMAND | TBIF_LPARAM; - int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, iItem, reinterpret_cast(&info)); + int index = GetButtonInfo(iItem, &info); if (index < 0) return E_FAIL; diff --git a/base/shell/rshell/CMenuToolbars.h b/base/shell/rshell/CMenuToolbars.h index 353e63b3d03..2866dbd699a 100644 --- a/base/shell/rshell/CMenuToolbars.h +++ b/base/shell/rshell/CMenuToolbars.h @@ -25,11 +25,11 @@ class CMenuFocusManager; #define WM_USER_ISTRACKEDITEM (WM_APP+41) #define WM_USER_CHANGETRACKEDITEM (WM_APP+42) -class CMenuToolbarBase +class CMenuToolbarBase : + public CToolbar { + CContainedWindow m_pager; private: - HWND m_hwnd; // May be the pager - HWND m_hwndToolbar; HFONT m_marlett; BOOL m_useFlatMenus; WNDPROC m_SubclassOld; @@ -55,10 +55,7 @@ protected: INT m_executeItem; DWORD_PTR m_executeData; -private: - static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - LRESULT SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + BOOL m_cancelingPopup; public: CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager); @@ -67,7 +64,7 @@ public: HRESULT IsWindowOwner(HWND hwnd); HRESULT CreateToolbar(HWND hwndParent, DWORD dwFlags); HRESULT GetWindow(HWND *phwnd); - HRESULT ShowWindow(BOOL fShow); + HRESULT ShowDW(BOOL fShow); HRESULT Close(); HRESULT OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); @@ -84,9 +81,6 @@ public: HRESULT PrepareExecuteItem(INT iItem); HRESULT ExecuteItem(); - HRESULT IsTrackedItem(INT index); - HRESULT ChangeTrackedItem(INT index, BOOL wasTracking, BOOL mouse); - HRESULT GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegralSize); HRESULT SetPosSize(int x, int y, int cx, int cy); @@ -105,6 +99,7 @@ public: HRESULT MenuBarMouseDown(INT iIndex); HRESULT MenuBarMouseUp(INT iIndex); HRESULT ProcessClick(INT iItem); + HRESULT BeforeCancelPopup(); protected: virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0; @@ -120,16 +115,28 @@ protected: HRESULT AddPlaceholder(); HRESULT ClearToolbar(); - HWND GetToolbar() { return m_hwndToolbar; } + HWND GetToolbar() { return m_hWnd; } private: HRESULT UpdateImageLists(); HRESULT OnPagerCalcSize(LPNMPGCALCSIZE csize); - HRESULT OnPopupTimer(DWORD timerId); HRESULT OnContextMenu(NMMOUSE * rclick); HRESULT OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult); HRESULT OnGetInfoTip(NMTBGETINFOTIP * tip); + + LRESULT IsTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT ChangeTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnWinEventWrap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + HRESULT OnPopupTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + + BEGIN_MSG_MAP(CMenuToolbarBase) + MESSAGE_HANDLER(WM_USER_ISTRACKEDITEM, IsTrackedItem) + MESSAGE_HANDLER(WM_USER_CHANGETRACKEDITEM, ChangeTrackedItem) + MESSAGE_HANDLER(WM_COMMAND, OnWinEventWrap) + MESSAGE_HANDLER(WM_NOTIFY, OnWinEventWrap) + MESSAGE_HANDLER(WM_TIMER, OnPopupTimer) + END_MSG_MAP() }; class CMenuStaticToolbar : diff --git a/base/shell/rshell/precomp.h b/base/shell/rshell/precomp.h index 4245975af27..a912f938b85 100644 --- a/base/shell/rshell/precomp.h +++ b/base/shell/rshell/precomp.h @@ -58,8 +58,11 @@ #include #include +#include #include +#include + #include #if _MSC_VER diff --git a/include/reactos/rosctrls.h b/include/reactos/rosctrls.h index 7d7735816a2..81aaf049fc3 100644 --- a/include/reactos/rosctrls.h +++ b/include/reactos/rosctrls.h @@ -253,6 +253,11 @@ public: // Configuration methods return SendMessageW(TB_GETHOTITEM); } + DWORD SetHotItem(INT item) + { + return SendMessageW(TB_SETHOTITEM, item); + } + public: // Button list management methods int GetButtonCount() { @@ -261,22 +266,22 @@ public: // Button list management methods DWORD GetButton(int index, TBBUTTON * btn) { - return SendMessageW(TB_GETBUTTON, index, (LPARAM) btn); + return SendMessageW(TB_GETBUTTON, index, reinterpret_cast(btn)); } DWORD AddButton(TBBUTTON * btn) { - return SendMessageW(TB_ADDBUTTONS, 1, (LPARAM) btn); + return SendMessageW(TB_ADDBUTTONS, 1, reinterpret_cast(btn)); } DWORD AddButtons(int count, TBBUTTON * buttons) { - return SendMessageW(TB_ADDBUTTONS, count, (LPARAM) buttons); + return SendMessageW(TB_ADDBUTTONS, count, reinterpret_cast(buttons)); } DWORD InsertButton(int insertAt, TBBUTTON * btn) { - return SendMessageW(TB_INSERTBUTTON, insertAt, (LPARAM) btn); + return SendMessageW(TB_INSERTBUTTON, insertAt, reinterpret_cast(btn)); } DWORD MoveButton(int oldIndex, int newIndex) @@ -291,18 +296,28 @@ public: // Button list management methods DWORD GetButtonInfo(int cmdId, TBBUTTONINFO * info) { - return SendMessageW(TB_GETBUTTONINFO, cmdId, (LPARAM) info); + return SendMessageW(TB_GETBUTTONINFO, cmdId, reinterpret_cast(info)); } DWORD SetButtonInfo(int cmdId, TBBUTTONINFO * info) { - return SendMessageW(TB_SETBUTTONINFO, cmdId, (LPARAM) info); + return SendMessageW(TB_SETBUTTONINFO, cmdId, reinterpret_cast(info)); + } + + DWORD CheckButton(int cmdId, BOOL bCheck) + { + return SendMessageW(TB_CHECKBUTTON, cmdId, MAKELPARAM(bCheck, 0)); } public: // Layout management methods + DWORD GetButtonSize() + { + return SendMessageW(TB_GETBUTTONSIZE); + } + DWORD SetButtonSize(int w, int h) { - return SendMessageW(TB_SETBUTTONSIZE, 0, MAKELONG(w, h)); + return SendMessageW(TB_SETBUTTONSIZE, 0, MAKELPARAM(w, h)); } DWORD AutoSize() @@ -310,19 +325,29 @@ public: // Layout management methods return SendMessageW(TB_AUTOSIZE); } + DWORD GetMaxSize(LPSIZE size) + { + return SendMessageW(TB_GETMAXSIZE, 0, reinterpret_cast(size)); + } + + DWORD GetIdealSize(BOOL useHeight, LPSIZE size) + { + return SendMessageW(TB_GETIDEALSIZE, useHeight, reinterpret_cast(size)); + } + DWORD GetMetrics(TBMETRICS * tbm) { - return SendMessageW(TB_GETMETRICS, 0, (LPARAM) tbm); + return SendMessageW(TB_GETMETRICS, 0, reinterpret_cast(tbm)); } DWORD SetMetrics(TBMETRICS * tbm) { - return SendMessageW(TB_SETMETRICS, 0, (LPARAM) tbm); + return SendMessageW(TB_SETMETRICS, 0, reinterpret_cast(tbm)); } DWORD GetItemRect(int index, LPRECT prcItem) { - return SendMessageW(TB_GETITEMRECT, index, (LPARAM) prcItem); + return SendMessageW(TB_GETITEMRECT, index, reinterpret_cast(prcItem)); } DWORD SetRedraw(BOOL bEnable) @@ -330,16 +355,26 @@ public: // Layout management methods return SendMessageW(WM_SETREDRAW, bEnable); } + DWORD GetPadding() + { + return SendMessageW(TB_GETPADDING); + } + + DWORD SetPadding(int x, int y) + { + return SendMessageW(TB_SETPADDING, 0, MAKELPARAM(x, y)); + } + public: // Image list management methods DWORD SetImageList(HIMAGELIST himl) { - return SendMessageW(TB_SETIMAGELIST, 0, (LPARAM) himl); + return SendMessageW(TB_SETIMAGELIST, 0, reinterpret_cast(himl)); } public: // Other methods INT HitTest(PPOINT ppt) { - return (INT) SendMessageW(TB_HITTEST, 0, (LPARAM) ppt); + return (INT) SendMessageW(TB_HITTEST, 0, reinterpret_cast(ppt)); } public: // Utility methods -- 2.17.1