Author: dquintana
Date: Mon Apr 7 18:41:47 2014
New Revision: 62681
URL:
http://svn.reactos.org/svn/reactos?rev=62681&view=rev
Log:
[RSHELL]
* Some code improvements, refactoring, and commenting.
* Using alternative method of handling hot-tracking, which does not break in win2003.
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/CMenuToolbars.cpp
branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] Mon Apr 7
18:41:47 2014
@@ -260,26 +260,26 @@
HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
{
- SIZE sizeStatic = { 0 };
- SIZE sizeShlFld = { 0 };
+ SIZE maxStatic = { 0 };
+ SIZE maxShlFld = { 0 };
HRESULT hr = S_OK;
if (m_staticToolbar != NULL)
- hr = m_staticToolbar->GetIdealSize(sizeStatic);
+ hr = m_staticToolbar->GetSizes(NULL, &maxStatic, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_SFToolbar != NULL)
- hr = m_SFToolbar->GetIdealSize(sizeShlFld);
+ hr = m_SFToolbar->GetSizes(NULL, &maxShlFld, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_staticToolbar == NULL && m_SFToolbar == NULL)
return E_FAIL;
- int sy = min(prc->bottom - prc->top, sizeStatic.cy + sizeShlFld.cy);
-
- int syStatic = sizeStatic.cy;
+ int sy = min(prc->bottom - prc->top, maxStatic.cy + maxShlFld.cy);
+
+ int syStatic = maxStatic.cy;
int syShlFld = sy - syStatic;
if (m_SFToolbar)
@@ -306,28 +306,46 @@
DWORD dwViewMode,
DESKBANDINFO *pdbi)
{
- SIZE sizeStatic = { 0 };
- SIZE sizeShlFld = { 0 };
+ SIZE minStatic = { 0 };
+ SIZE minShlFld = { 0 };
+ SIZE maxStatic = { 0 };
+ SIZE maxShlFld = { 0 };
+ SIZE intStatic = { 0 };
+ SIZE intShlFld = { 0 };
HRESULT hr = S_OK;
if (m_staticToolbar != NULL)
- hr = m_staticToolbar->GetIdealSize(sizeStatic);
+ hr = m_staticToolbar->GetSizes(&minStatic, &maxStatic,
&intStatic);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_SFToolbar != NULL)
- hr = m_SFToolbar->GetIdealSize(sizeShlFld);
+ hr = m_SFToolbar->GetSizes(&minShlFld, &maxShlFld, &intShlFld);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_staticToolbar == NULL && m_SFToolbar == NULL)
return E_FAIL;
- pdbi->ptMinSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
- pdbi->ptMinSize.y = sizeStatic.cy + sizeShlFld.cy;
- pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
- pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
+ if (m_dwFlags & SMINIT_VERTICAL)
+ {
+ pdbi->ptMinSize.x = max(minStatic.cx, minStatic.cx) + 20;
+ pdbi->ptMinSize.y = minStatic.cy + minStatic.cy;
+ pdbi->ptMaxSize.x = max(maxStatic.cx, maxShlFld.cx) + 20;
+ pdbi->ptMaxSize.y = maxStatic.cy + maxShlFld.cy;
+ pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
+ }
+ else
+ {
+ pdbi->ptMinSize.x = minStatic.cx + minStatic.cx;
+ pdbi->ptMinSize.y = max(minStatic.cy, minStatic.cy);
+ pdbi->ptMaxSize.x = maxStatic.cx + maxShlFld.cx;
+ pdbi->ptMaxSize.y = max(maxStatic.cy, maxShlFld.cy);
+ }
+ pdbi->ptIntegral.x = max(intStatic.cx, intStatic.cx);
+ pdbi->ptIntegral.y = max(intStatic.cy, intShlFld.cy);
+ pdbi->ptActual = pdbi->ptMinSize;
return S_OK;
}
@@ -652,12 +670,10 @@
smData.uId = id;
smData.uIdParent = m_uId;
smData.uIdAncestor = m_uIdAncestor;
+ smData.pidlItem = pidl;
smData.hwnd = hwnd;
- smData.pidlItem = pidl;
- if (m_staticToolbar)
- {
+ if (m_hmenu)
smData.hmenu = m_hmenu;
- }
smData.pvUserData = NULL;
if (m_SFToolbar)
m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder,
IID_PPV_ARG(IShellFolder, &smData.psf));
@@ -668,7 +684,7 @@
return hr;
}
-HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT&
rcExclude)
+HRESULT CMenuBand::_TrackSubMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
{
TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
@@ -688,6 +704,41 @@
_DisableMouseTrack(FALSE);
return S_OK;
+}
+
+HRESULT CMenuBand::_TrackContextMenu(IContextMenu * contextMenu, INT x, INT y)
+{
+ HRESULT hr;
+ UINT uCommand;
+ HMENU popup = CreatePopupMenu();
+
+ if (popup == NULL)
+ return E_FAIL;
+
+ hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ DestroyMenu(popup);
+ return hr;
+ }
+
+ HWND hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
+
+ m_focusManager->PushTrackedPopup(popup);
+ uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_menuOwner, NULL);
+ m_focusManager->PopTrackedPopup(popup);
+
+ if (uCommand == 0)
+ return S_FALSE;
+
+ CMINVOKECOMMANDINFO cmi = { 0 };
+ cmi.cbSize = sizeof(cmi);
+ cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+ cmi.hwnd = hwnd;
+ hr = contextMenu->InvokeCommand(&cmi);
+
+ DestroyMenu(popup);
+ return hr;
}
HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
@@ -728,119 +779,91 @@
return S_OK;
}
+HRESULT CMenuBand::_KeyboardItemChange(DWORD change)
+{
+ HRESULT hr;
+ CMenuToolbarBase *tb = m_hotBar;
+
+ if (!tb)
+ {
+ // If no hot item was selected
+ // choose the first toolbar (prefer shell-folder, which will be positionedat the
top)
+
+ if (m_SFToolbar)
+ tb = m_SFToolbar;
+ else
+ tb = m_staticToolbar;
+ }
+
+ // Ask the first toolbar to change
+ hr = tb->KeyboardItemChange(change);
+
+ if (hr != S_FALSE)
+ return hr;
+
+ // Select the second toolbar based on the first
+ if (tb == m_SFToolbar)
+ tb = m_staticToolbar;
+ else
+ tb = m_SFToolbar;
+
+ if (!tb)
+ return hr;
+
+ // Ask the second toolbar to change
+ return tb->KeyboardItemChange(change == VK_DOWN ? VK_END : VK_HOME);
+}
+
HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
{
HRESULT hr;
- if (!(m_dwFlags & SMINIT_VERTICAL))
- {
- if (changeType == MPOS_SELECTRIGHT)
+
+ if (m_dwFlags & SMINIT_VERTICAL)
+ {
+ switch (changeType)
{
- SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
- if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
- {
- DbgPrint("SF Toolbars in Horizontal menus is not
implemented.\n");
- return S_FALSE;
- }
- else if (m_staticToolbar && m_hotBar == m_staticToolbar)
- {
- hr = m_staticToolbar->KeyboardItemChange(VK_DOWN);
- if (hr == S_FALSE)
- {
- if (m_SFToolbar)
- return m_SFToolbar->KeyboardItemChange(VK_HOME);
- else
- return m_staticToolbar->KeyboardItemChange(VK_HOME);
- }
+ case VK_UP:
+ case VK_DOWN:
+ return _KeyboardItemChange(changeType);
+
+ // TODO: Left/Right across multi-column menus, if they ever work.
+ case VK_LEFT:
+ changeType = MPOS_SELECTLEFT;
+ break;
+ case VK_RIGHT:
+ changeType = MPOS_SELECTRIGHT;
+ break;
+ }
+ }
+ else
+ {
+ // In horizontal menubars, left/right are equivalent to vertical's up/down
+ switch(changeType)
+ {
+ case VK_LEFT:
+ hr = _KeyboardItemChange(VK_UP);
+ if (hr != S_FALSE)
return hr;
- }
+ case VK_RIGHT:
+ hr = _KeyboardItemChange(VK_DOWN);
+ if (hr != S_FALSE)
+ return hr;
}
- else if (changeType == MPOS_SELECTLEFT)
+ }
+
+ switch (changeType)
+ {
+ case MPOS_SELECTLEFT:
+ if (!m_subMenuParent)
{
- SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
- if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar ==
NULL))
- {
- hr = m_staticToolbar->KeyboardItemChange(VK_UP);
- if (hr == S_FALSE)
- {
- if (m_SFToolbar)
- return m_SFToolbar->KeyboardItemChange(VK_END);
- else
- return m_staticToolbar->KeyboardItemChange(VK_END);
- }
- return hr;
- }
- else if (m_SFToolbar && m_hotBar == m_SFToolbar)
- {
- DbgPrint("SF Toolbars in Horizontal menus is not
implemented.\n");
- return S_FALSE;
- }
+ if (m_subMenuChild)
+ return m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ return S_OK;
}
- }
- else if (changeType == VK_DOWN)
- {
- if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
- {
- hr = m_SFToolbar->KeyboardItemChange(VK_DOWN);
- if (hr == S_FALSE)
- {
- if (m_staticToolbar)
- return m_staticToolbar->KeyboardItemChange(VK_HOME);
- else
- return m_SFToolbar->KeyboardItemChange(VK_HOME);
- }
- return hr;
- }
- else if (m_staticToolbar && m_hotBar == m_staticToolbar)
- {
- hr = m_staticToolbar->KeyboardItemChange(VK_DOWN);
- if (hr == S_FALSE)
- {
- if (m_SFToolbar)
- return m_SFToolbar->KeyboardItemChange(VK_HOME);
- else
- return m_staticToolbar->KeyboardItemChange(VK_HOME);
- }
- return hr;
- }
- }
- else if (changeType == VK_UP)
- {
- if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar ==
NULL))
- {
- hr = m_staticToolbar->KeyboardItemChange(VK_UP);
- if (hr == S_FALSE)
- {
- if (m_SFToolbar)
- return m_SFToolbar->KeyboardItemChange(VK_END);
- else
- return m_staticToolbar->KeyboardItemChange(VK_END);
- }
- return hr;
- }
- else if (m_SFToolbar && m_hotBar == m_SFToolbar)
- {
- hr = m_SFToolbar->KeyboardItemChange(VK_UP);
- if (hr == S_FALSE)
- {
- if (m_staticToolbar)
- return m_staticToolbar->KeyboardItemChange(VK_END);
- else
- return m_SFToolbar->KeyboardItemChange(VK_END);
- }
- return hr;
- }
- }
- else if (changeType == MPOS_SELECTLEFT)
- {
- if (m_subMenuChild)
- m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
- if (!m_subMenuParent)
- return S_OK;
return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
- }
- else if (changeType == MPOS_SELECTRIGHT)
- {
+
+ case MPOS_SELECTRIGHT:
if (m_hotBar && m_hotItem >= 0)
{
if (m_hotBar->PopupItem(m_hotItem) == S_OK)
@@ -848,14 +871,14 @@
}
if (!m_subMenuParent)
return S_OK;
- return m_subMenuParent->OnSelect(changeType);
- }
- else
- {
+ return m_subMenuParent->OnSelect(MPOS_SELECTRIGHT);
+
+ default:
if (!m_subMenuParent)
return S_OK;
return m_subMenuParent->OnSelect(changeType);
}
+
return S_OK;
}
@@ -868,8 +891,60 @@
return hr;
}
-HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
-{
+HRESULT CMenuBand::_OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL *
pExclude)
+{
+ HRESULT hr = 0;
+ IBandSite* pBandSite;
+ IDeskBar* pDeskBar;
+
+ // Create the necessary objects
+
+#if USE_SYSTEM_MENUSITE
+ hr = CoCreateInstance(CLSID_MenuBandSite,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARG(IBandSite, &pBandSite));
+#else
+ hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
+#endif
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+#if WRAP_MENUSITE
+ hr = CMenuSite_Wrapper(pBandSite, IID_PPV_ARG(IBandSite, &pBandSite));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+#endif
+
+#if USE_SYSTEM_MENUDESKBAR
+ hr = CoCreateInstance(CLSID_MenuDeskBar,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARG(IDeskBar, &pDeskBar));
+#else
+ hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
+#endif
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+#if WRAP_MENUDESKBAR
+ hr = CMenuDeskBar_Wrapper(pDeskBar, IID_PPV_ARG(IDeskBar, &pDeskBar));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+#endif
+
+ hr = pDeskBar->SetClient(pBandSite);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ hr = pBandSite->AddBand(childShellMenu);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ //
+ CComPtr<IMenuPopup> popup;
+ hr = pDeskBar->QueryInterface(IID_PPV_ARG(IMenuPopup, &popup));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
m_subMenuChild = popup;
if (m_subMenuParent)
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] Mon Apr 7
18:41:47 2014
@@ -175,13 +175,14 @@
HRESULT _CallCBWithItemId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM
lParam);
- HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT&
rcExclude);
+ HRESULT _TrackSubMenu(HMENU popup, INT x, INT y, RECT& rcExclude);
+ HRESULT _TrackContextMenu(IContextMenu * popup, INT x, INT y);
HRESULT _GetTopLevelWindow(HWND*topLevel);
HRESULT _ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags);
HRESULT _ChangePopupItem(CMenuToolbarBase * tb, INT id);
HRESULT _MenuItemHotTrack(DWORD changeType);
HRESULT _CancelCurrentPopup();
- HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude);
+ HRESULT _OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL *
pExclude);
HRESULT _DisableMouseTrack(BOOL bDisable);
HRESULT _SetChildBand(CMenuBand * child);
HRESULT _SetParentBand(CMenuBand * parent);
@@ -195,5 +196,6 @@
}
private:
+ HRESULT _KeyboardItemChange(DWORD change);
HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST
pidl = NULL);
};
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1] Mon
Apr 7 18:41:47 2014
@@ -261,7 +261,7 @@
// Don't do anything if another window is capturing the mouse.
HWND cCapture = ::GetCapture();
- if (cCapture && cCapture != m_captureHwnd)
+ if (cCapture && cCapture != m_captureHwnd && m_current->type !=
TrackedMenuEntry)
return TRUE;
m_ptPrev = pt;
@@ -283,7 +283,8 @@
{
m_entryUnderMouse->mb->_ChangeHotItem(NULL, -1, HICF_MOUSE);
}
- SetCapture(NULL);
+ if (cCapture == m_captureHwnd)
+ SetCapture(NULL);
}
}
@@ -303,7 +304,8 @@
if (m_current->type == TrackedMenuEntry)
SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0);
PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, isTracking);
- return FALSE;
+ if (m_current->type == TrackedMenuEntry)
+ return FALSE;
}
}
@@ -311,10 +313,10 @@
{
if (entry)
{
- SetCapture(child);
-
if (m_current->type == MenuPopupEntry)
{
+ //SetCapture(child);
+
ScreenToClient(child, &pt2);
SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x,
pt2.y));
}
@@ -399,6 +401,10 @@
case WM_MOUSEMOVE:
callNext = ProcessMouseMove(msg);
break;
+ case WM_MOUSELEAVE:
+ callNext = ProcessMouseMove(msg);
+ //callNext = ProcessMouseLeave(msg);
+ break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if (m_current->type == MenuPopupEntry)
@@ -406,16 +412,17 @@
DisableMouseTrack(m_current->hwnd, TRUE);
switch (msg->wParam)
{
+ case VK_ESCAPE:
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
break;
case VK_LEFT:
- m_current->mb->_MenuItemHotTrack(MPOS_SELECTLEFT);
+ m_current->mb->_MenuItemHotTrack(VK_LEFT);
break;
case VK_RIGHT:
- m_current->mb->_MenuItemHotTrack(MPOS_SELECTRIGHT);
+ m_current->mb->_MenuItemHotTrack(VK_RIGHT);
break;
case VK_UP:
m_current->mb->_MenuItemHotTrack(VK_UP);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1] Mon Apr 7
18:41:47 2014
@@ -159,7 +159,7 @@
HRESULT CMenuToolbarBase::OnPagerCalcSize(LPNMPGCALCSIZE csize)
{
SIZE tbs;
- GetIdealSize(tbs);
+ GetSizes(NULL, &tbs, NULL);
if (csize->dwFlag == PGF_CALCHEIGHT)
{
csize->iHeight = tbs.cy;
@@ -284,12 +284,16 @@
m_menuBand(menuBand),
m_hwndToolbar(NULL),
m_dwMenuFlags(0),
- m_hasIdealSize(FALSE),
+ m_hasSizes(FALSE),
m_usePager(usePager),
m_hotItem(-1),
m_popupItem(-1),
- m_isTracking(FALSE)
-{
+ m_isTrackingPopup(FALSE)
+{
+ m_idealSize.cx = 0;
+ m_idealSize.cy = 0;
+ m_itemSize.cx = 0;
+ m_itemSize.cy = 0;
m_marlett = CreateFont(
0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
@@ -452,18 +456,38 @@
return S_OK;
}
-HRESULT CMenuToolbarBase::GetIdealSize(SIZE& size)
-{
- size.cx = size.cy = 0;
-
- if (m_hwndToolbar && !m_hasIdealSize)
- {
- SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0);
- SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0,
reinterpret_cast<LPARAM>(&m_idealSize));
- m_hasIdealSize = TRUE;
- }
-
- size = m_idealSize;
+HRESULT CMenuToolbarBase::GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegralSize)
+{
+ if (pMinSize)
+ *pMinSize = m_idealSize;
+ if (pMaxSize)
+ *pMaxSize = m_idealSize;
+ if (pIntegralSize)
+ *pIntegralSize = m_itemSize;
+
+ if (m_hasSizes)
+ return S_OK;
+
+ if (!m_hwndToolbar)
+ 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<LPARAM>(&m_idealSize));
+ SendMessageW(m_hwndToolbar, TB_GETIDEALSIZE, (m_initFlags & SMINIT_VERTICAL) !=
0, reinterpret_cast<LPARAM>(&m_idealSize));
+
+ // Obtain the button size, to be used as the integral size
+ DWORD size = SendMessageW(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
+ m_itemSize.cx = GET_X_LPARAM(size);
+ m_itemSize.cy = GET_Y_LPARAM(size);
+ m_hasSizes = TRUE;
+
+ if (pMinSize)
+ *pMinSize = m_idealSize;
+ if (pMaxSize)
+ *pMaxSize = m_idealSize;
+ if (pIntegralSize)
+ *pIntegralSize = m_itemSize;
return S_OK;
}
@@ -560,46 +584,21 @@
return S_FALSE;
}
-HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult)
-{
+HRESULT CMenuToolbarBase::ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD
dwFlags)
+{
+ // Ignore the change if it already matches the stored info
+ if (m_hotBar == toolbar && m_hotItem == item)
+ return S_FALSE;
+
// 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;
+ if (m_disableMouseTrack && dwFlags & HICF_MOUSE)
+ {
DbgPrint("Hot item change prevented by DisableMouseTrack\n");
return S_OK;
}
- HRESULT hr = S_OK;
- if (hot->dwFlags & HICF_LEAVING)
- {
- // Only notify of LEAVING if this was the hot toolbar.
- if (m_hotBar == this)
- {
- 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;
-
+ // Notify the toolbar if the hot-tracking left this toolbar
if (m_hotBar == this && toolbar != this)
{
SendMessage(m_hwndToolbar, TB_SETHOTITEM, (WPARAM)-1, 0);
@@ -623,8 +622,9 @@
m_timerEnabled = TRUE;
DbgPrint("SetTimer called with m_hotItem=%d\n", m_hotItem);
}
- else if (m_isTracking)
+ else if (m_isTrackingPopup)
{
+ // If the menubar has an open submenu, switch to the new item's
submenu immediately
PopupItem(m_hotItem);
}
}
@@ -646,13 +646,15 @@
HRESULT CMenuToolbarBase::ChangePopupItem(CMenuToolbarBase * toolbar, INT item)
{
+ // Ignore the change if it already matches the stored info
if (m_popupBar == toolbar && m_popupItem == item)
return S_FALSE;
+ // Notify the toolbar if the popup-tracking this toolbar
if (m_popupBar == this && toolbar != this)
{
SendMessage(m_hwndToolbar, TB_CHECKBUTTON, m_popupItem, FALSE);
- m_isTracking = FALSE;
+ m_isTrackingPopup = FALSE;
}
m_popupBar = toolbar;
@@ -693,7 +695,7 @@
return E_FAIL;
DbgPrint("Changing tracked item to %d...\n", index);
- m_isTracking = wasTracking;
+ m_isTrackingPopup = wasTracking;
m_menuBand->_ChangeHotItem(this, btn.idCommand, HICF_MOUSE);
return S_OK;
@@ -701,10 +703,7 @@
HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, IShellMenu*
childShellMenu)
{
- IBandSite* pBandSite;
- IDeskBar* pDeskBar;
-
- HRESULT hr = 0;
+ // Calculate the submenu position and exclude area
RECT rc = { 0 };
RECT rcx = { 0 };
@@ -732,81 +731,31 @@
pt.y = a.y - 3;
}
-#if USE_SYSTEM_MENUSITE
- hr = CoCreateInstance(CLSID_MenuBandSite,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARG(IBandSite, &pBandSite));
-#else
- hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
-#endif
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-#if WRAP_MENUSITE
- hr = CMenuSite_Wrapper(pBandSite, IID_PPV_ARG(IBandSite, &pBandSite));
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-#endif
-
-#if USE_SYSTEM_MENUDESKBAR
- hr = CoCreateInstance(CLSID_MenuDeskBar,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARG(IDeskBar, &pDeskBar));
-#else
- hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
-#endif
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-#if WRAP_MENUDESKBAR
- hr = CMenuDeskBar_Wrapper(pDeskBar, IID_PPV_ARG(IDeskBar, &pDeskBar));
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-#endif
-
- hr = pDeskBar->SetClient(pBandSite);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- hr = pBandSite->AddBand(childShellMenu);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- CComPtr<IMenuPopup> popup;
- hr = pDeskBar->QueryInterface(IID_PPV_ARG(IMenuPopup, &popup));
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- m_isTracking = TRUE;
+ // Display the submenu
+ m_isTrackingPopup = TRUE;
m_menuBand->_ChangePopupItem(this, iItem);
- m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl);
+ m_menuBand->_OnPopupSubMenu(childShellMenu, &pt, &rcl);
return S_OK;
}
HRESULT CMenuToolbarBase::PopupSubMenu(UINT iItem, UINT index, HMENU menu)
{
+ // Calculate the submenu position and exclude area
RECT rc = { 0 };
- RECT rcx = { 0 };
if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index,
reinterpret_cast<LPARAM>(&rc)))
return E_FAIL;
-
- GetClientRect(m_hwndToolbar, &rcx);
-
+
POINT a = { rc.left, rc.top };
POINT b = { rc.right, rc.bottom };
- POINT c = { rc.left, rc.top };
- POINT d = { rc.right, rc.bottom };
ClientToScreen(m_hwndToolbar, &a);
ClientToScreen(m_hwndToolbar, &b);
- ClientToScreen(m_hwndToolbar, &c);
- ClientToScreen(m_hwndToolbar, &d);
POINT pt = { a.x, b.y };
- RECT rcl = { c.x, c.y, d.x, d.y };
+ RECT rcl = { a.x, a.y, b.x, b.y };
if (m_initFlags & SMINIT_VERTICAL)
{
@@ -816,45 +765,24 @@
HMENU popup = GetSubMenu(menu, index);
- m_isTracking = TRUE;
-
+ // Display the submenu
+ m_isTrackingPopup = TRUE;
m_menuBand->_ChangePopupItem(this, iItem);
- m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, pt.x, pt.y, rcl);
+ m_menuBand->_TrackSubMenu(popup, pt.x, pt.y, rcl);
m_menuBand->_ChangePopupItem(NULL, -1);
-
- m_isTracking = FALSE;
+ m_isTrackingPopup = FALSE;
return S_OK;
}
HRESULT CMenuToolbarBase::DoContextMenu(IContextMenu* contextMenu)
{
- HRESULT hr;
- HMENU hPopup = CreatePopupMenu();
-
- if (hPopup == NULL)
- return E_FAIL;
-
- hr = contextMenu->QueryContextMenu(hPopup, 0, 0, UINT_MAX, CMF_NORMAL);
- if (FAILED_UNEXPECTEDLY(hr))
- {
- DestroyMenu(hPopup);
- return hr;
- }
-
+ // Calculate the context menu position
DWORD dwPos = GetMessagePos();
- UINT uCommand = ::TrackPopupMenu(hPopup, TPM_RETURNCMD, GET_X_LPARAM(dwPos),
GET_Y_LPARAM(dwPos), 0, m_hwnd, NULL);
- if (uCommand == 0)
- return S_FALSE;
-
- CMINVOKECOMMANDINFO cmi = { 0 };
- cmi.cbSize = sizeof(cmi);
- cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
- cmi.hwnd = m_hwnd;
- hr = contextMenu->InvokeCommand(&cmi);
-
- DestroyMenu(hPopup);
- return hr;
+ POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
+
+ // Display the submenu
+ return m_menuBand->_TrackContextMenu(contextMenu, pt.x, pt.y);
}
HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
@@ -866,6 +794,13 @@
return S_OK;
}
+ // If a button is clicked while a submenu was open, cancel the submenu.
+ if (!(m_initFlags & SMINIT_VERTICAL) && m_isTrackingPopup)
+ {
+ DbgPrint("OnCommand cancelled because it was tracking submenu.\n");
+ return S_FALSE;
+ }
+
*theResult = 0;
m_menuBand->_KillPopupTimers();
@@ -883,7 +818,7 @@
if (FAILED_UNEXPECTEDLY(hr))
return hr;
- return S_OK; // filter out a possible S_FALSE from here.
+ return OnCommandInternal(wParam, lParam, theResult);
}
HRESULT CMenuToolbarBase::KeyboardItemChange(DWORD dwSelectType)
@@ -948,7 +883,7 @@
if (prev != btn.idCommand)
{
DbgPrint("Setting Hot item to %d\n", index);
- SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
+ m_menuBand->_ChangeHotItem(this, index, 0);
}
return S_OK;
}
@@ -967,8 +902,9 @@
if (prev != -1)
{
DbgPrint("Setting Hot item to null\n");
- SendMessage(m_hwndToolbar, TB_SETHOTITEM, (WPARAM) -1, 0);
- }
+ m_menuBand->_ChangeHotItem(NULL, -1, 0);
+ }
+
return S_FALSE;
}
@@ -1219,25 +1155,8 @@
return DoContextMenu(contextMenu);
}
-HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
-{
- HRESULT hr;
-
- if (m_isTracking)
- {
- return S_FALSE;
- }
-
- hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- // in case the clicked item has a submenu, we do not need to execute the item
- if (hr == S_FALSE)
- {
- return hr;
- }
-
+HRESULT CMenuStaticToolbar::OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT
*theResult)
+{
return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
}
@@ -1313,7 +1232,6 @@
hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
- // FIXME: remove before deleting the toolbar or it will leak
// Fetch next item already, so we know if the current one is the last
hr = eidl->Next(1, &item, &fetched);
@@ -1399,21 +1317,10 @@
return DoContextMenu(contextMenu);
}
-HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
-{
- HRESULT hr;
- hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- // in case the clicked item has a submenu, we do not need to execute the item
- if (hr == S_FALSE)
- {
- DbgPrint("CMenuToolbarBase::OnCommand told us to cancel.\n");
- return hr;
- }
-
+HRESULT CMenuSFToolbar::OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT
*theResult)
+{
DWORD_PTR data;
+
GetDataFromId(wParam, NULL, &data);
return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(data),
SMC_SFEXEC, 0, 0);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] Mon Apr 7
18:41:47 2014
@@ -40,8 +40,9 @@
CMenuBand * m_menuBand;
HWND m_hwndToolbar;
DWORD m_dwMenuFlags;
- BOOL m_hasIdealSize;
+ BOOL m_hasSizes;
SIZE m_idealSize;
+ SIZE m_itemSize;
BOOL m_usePager;
CMenuToolbarBase * m_hotBar;
INT m_hotItem;
@@ -49,7 +50,7 @@
INT m_popupItem;
DWORD m_initFlags;
- BOOL m_isTracking;
+ BOOL m_isTrackingPopup;
private:
static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam);
@@ -74,12 +75,11 @@
HRESULT DoContextMenu(IContextMenu* contextMenu);
HRESULT KeyboardItemChange(DWORD changeType);
- HRESULT OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult);
HRESULT IsTrackedItem(INT index);
HRESULT ChangeTrackedItem(INT index, BOOL wasTracking);
- HRESULT GetIdealSize(SIZE& size);
+ HRESULT GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegralSize);
HRESULT SetPosSize(int x, int y, int cx, int cy);
void InvalidateDraw();
@@ -96,7 +96,7 @@
HRESULT KillPopupTimer();
protected:
- virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
+ virtual HRESULT OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT *theResult) =
0;
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0;
virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData) = 0;
@@ -113,6 +113,7 @@
HRESULT UpdateImageLists();
private:
+ HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
HRESULT OnPagerCalcSize(LPNMPGCALCSIZE csize);
HRESULT OnPopupTimer(DWORD timerId);
HRESULT OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult);
@@ -133,7 +134,7 @@
HRESULT GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE);
- virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
+ virtual HRESULT OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
protected:
@@ -161,7 +162,7 @@
HRESULT GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void
**ppv);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE);
- virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
+ virtual HRESULT OnCommandInternal(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
protected: