Author: dquintana
Date: Fri Feb 21 10:00:00 2014
New Revision: 62280
URL:
http://svn.reactos.org/svn/reactos?rev=62280&view=rev
Log:
[RSHELL]
* CMenuBand, CMenuDeskBar: Improve the SubMenu hierarchy and OnSelect flow. Now the menu
will spread a FullCancel or Execute upwards and close the whole start menu.
CORE-7881
Modified:
branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
branches/shell-experiments/base/shell/rshell/logging/CMenuSiteWrap.cpp
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] Fri Feb 21
10:00:00 2014
@@ -140,7 +140,8 @@
CComPtr<IOleWindow> m_site;
CComPtr<IShellMenuCallback> m_psmc;
- CComPtr<IMenuPopup> m_childMenu;
+ CComPtr<IMenuPopup> m_subMenuChild;
+ CComPtr<IMenuPopup> m_subMenuParent;
UINT m_uId;
UINT m_uIdAncestor;
@@ -269,7 +270,7 @@
HRESULT _GetTopLevelWindow(HWND*topLevel);
HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id);
HRESULT _MenuItemHotTrack(DWORD changeType);
- HRESULT _OnPopupSubMenu(IMenuPopup * popup);
+ HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude);
BOOL UseBigIcons()
{
@@ -332,7 +333,7 @@
private:
// TODO: make dynamic
-#define MAX_RECURSE 100
+#define MAX_RECURSE 20
CMenuBand* m_bandStack[MAX_RECURSE];
int m_bandCount;
@@ -357,6 +358,8 @@
if (pItem)
*pItem = m_bandStack[m_bandCount];
+
+ m_bandStack[m_bandCount] = NULL;
return S_OK;
}
@@ -676,7 +679,7 @@
case WM_TIMER:
if (wParam == TIMERID_HOTTRACK)
{
- m_menuBand->_OnPopupSubMenu(NULL);
+ m_menuBand->_OnPopupSubMenu(NULL, NULL, NULL);
PopupItem(m_hotItem);
KillTimer(hWnd, TIMERID_HOTTRACK);
}
@@ -776,9 +779,7 @@
if (FAILED(hr))
return hr;
- popup->Popup(&pt, &rcl, MPPF_TOP | MPPF_RIGHT);
-
- m_menuBand->_OnPopupSubMenu(popup);
+ m_menuBand->_OnPopupSubMenu(popup, &pt, &rcl);
return S_OK;
}
@@ -1037,11 +1038,12 @@
HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- HRESULT hr = m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
- if (FAILED(hr))
- return hr;
-
- return CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ HRESULT hr;
+ hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ if (FAILED(hr))
+ return hr;
+
+ return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
}
HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
@@ -1099,12 +1101,8 @@
HRESULT CMenuSFToolbar::FillToolbar()
{
HRESULT hr;
- TBBUTTON tbb = { 0 };
int i = 0;
PWSTR MenuString;
-
- tbb.fsState = TBSTATE_ENABLED;
- tbb.fsStyle = 0;
IEnumIDList * eidl;
m_shellFolder->EnumObjects(m_hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
&eidl);
@@ -1115,6 +1113,10 @@
{
INT index = 0;
INT indexOpen = 0;
+
+ TBBUTTON tbb = { 0 };
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = 0;
CComPtr<IShellItem> psi;
SHCreateShellItem(NULL, m_shellFolder, item, &psi);
@@ -1222,9 +1224,12 @@
HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- HRESULT hr = m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0,
0);
-
- return CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ HRESULT hr;
+ hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ if (FAILED(hr))
+ return hr;
+
+ return m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
}
HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
@@ -1299,7 +1304,7 @@
m_useBigIcons(FALSE),
m_hotBar(NULL),
m_hotItem(-1),
- m_childMenu(NULL)
+ m_subMenuChild(NULL)
{
m_focusManager = CMenuFocusManager::AcquireManager();
}
@@ -1321,7 +1326,8 @@
UINT uIdAncestor,
DWORD dwFlags)
{
- m_psmc = psmc;
+ if (m_psmc != psmc)
+ m_psmc = psmc;
m_uId = uId;
m_uIdAncestor = uIdAncestor;
m_dwFlags = dwFlags;
@@ -1446,6 +1452,10 @@
return hr;
}
+ hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup,
&m_subMenuParent));
+ if (FAILED(hr))
+ return hr;
+
CComPtr<IOleWindow> pTopLevelWindow;
hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow,
&pTopLevelWindow));
if (FAILED(hr))
@@ -1498,7 +1508,10 @@
if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE,
reinterpret_cast<LPARAM>(&sizeStaticY));
if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE,
reinterpret_cast<LPARAM>(&sizeShlFldY));
- int sy = max(prc->bottom - prc->top, sizeStaticY.cy + sizeShlFldY.cy);
+ int sy = min(prc->bottom - prc->top, sizeStaticY.cy + sizeShlFldY.cy);
+
+ int syStatic = sizeStaticY.cy;
+ int syShlFld = sy - syStatic;
if (hwndShlFld)
{
@@ -1506,7 +1519,7 @@
prc->left,
prc->top,
prc->right - prc->left,
- sizeShlFldY.cy,
+ syShlFld,
0);
DWORD btnSize = SendMessage(hwndShlFld, TB_GETBUTTONSIZE, 0, 0);
SendMessage(hwndShlFld, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right -
prc->left, HIWORD(btnSize)));
@@ -1515,9 +1528,9 @@
{
SetWindowPos(hwndStatic, hwndShlFld,
prc->left,
- prc->top + sizeShlFldY.cy,
+ prc->top + syShlFld,
prc->right - prc->left,
- sy - sizeShlFldY.cy,
+ syStatic,
0);
DWORD btnSize = SendMessage(hwndStatic, TB_GETBUTTONSIZE, 0, 0);
SendMessage(hwndStatic, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right -
prc->left, HIWORD(btnSize)));
@@ -1572,6 +1585,9 @@
if (hwndStatic) SendMessageW(hwndStatic, TB_GETMAXSIZE, 0,
reinterpret_cast<LPARAM>(&sizeStatic));
if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETMAXSIZE, 0,
reinterpret_cast<LPARAM>(&sizeShlFld));
+
+ sizeStatic.cx += 64;
+ sizeShlFld.cx += 64;
pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx); // ignored
pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
@@ -1629,7 +1645,7 @@
else
hr = m_focusManager->PopMenu(this);
- return hr;
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
@@ -1659,13 +1675,8 @@
HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
{
HRESULT hr;
- CComPtr<IMenuPopup> pmp;
-
- hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup,
&pmp));
- if (FAILED(hr))
- return hr;
-
- hr = pmp->SetSubMenu(this, fActivate);
+
+ hr = m_subMenuParent->SetSubMenu(this, fActivate);
if (FAILED(hr))
return hr;
@@ -1776,17 +1787,30 @@
HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
{
- if (dwSelectType != MPOS_CANCELLEVEL)
- {
- if (dwSelectType == MPOS_SELECTLEFT)
- {
- dwSelectType = MPOS_CANCELLEVEL;
- }
- CComPtr<IMenuPopup> pmp;
- HRESULT hr = IUnknown_QueryService(m_site, SID_SMenuPopup,
IID_PPV_ARG(IMenuPopup, &pmp));
- if (FAILED(hr))
- return hr;
- return pmp->OnSelect(dwSelectType);
+ switch (dwSelectType)
+ {
+ case MPOS_CHILDTRACKING:
+ // TODO: Cancel timers?
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_SELECTLEFT:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_SELECTRIGHT:
+ if (m_hotBar && m_hotItem >= 0)
+ {
+ // TODO: popup the current child if it has subitems, otherwise spread up.
+ }
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_EXECUTE:
+ case MPOS_FULLCANCEL:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(dwSelectType);
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_CANCELLEVEL:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(dwSelectType);
+ break;
}
return S_FALSE;
}
@@ -2180,28 +2204,25 @@
}
else
{
- CComPtr<IMenuPopup> pmp;
- hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup,
&pmp));
+ m_subMenuParent->OnSelect(changeType);
+ }
+ return S_OK;
+}
+
+
+HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
+{
+ if (m_subMenuChild)
+ {
+ HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
if (FAILED(hr))
return hr;
- pmp->OnSelect(changeType);
- }
- return S_OK;
-}
-
-
-HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup)
-{
- if (m_childMenu)
- {
- HRESULT hr = m_childMenu->OnSelect(MPOS_CANCELLEVEL);
- if (FAILED(hr))
- return hr;
- }
- m_childMenu = popup;
- if (m_childMenu)
- {
- return m_childMenu->SetSubMenu(this, TRUE);
- }
- return S_OK;
-}
+ }
+ m_subMenuChild = popup;
+ if (popup)
+ {
+ IUnknown_SetSite(popup, m_subMenuParent);
+ popup->Popup(pAt, pExclude, MPPF_TOP | MPPF_RIGHT);
+ }
+ return S_OK;
+}
Modified: branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] Fri Feb 21
10:00:00 2014
@@ -47,11 +47,14 @@
CComPtr<IUnknown> m_Site;
CComPtr<IUnknown> m_Client;
CComPtr<IMenuPopup> m_SubMenuParent;
+ CComPtr<IMenuPopup> m_SubMenuChild;
HWND m_ClientWindow;
DWORD m_IconSize;
HBITMAP m_Banner;
+
+ INT m_Level;
public:
CMenuDeskBar();
@@ -130,6 +133,8 @@
LRESULT _OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
&bHandled);
LRESULT _OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+
+ HRESULT _CloseBar();
};
extern "C"
@@ -150,14 +155,18 @@
return hr;
}
+INT deskBarCount=0;
+
CMenuDeskBar::CMenuDeskBar() :
m_Client(NULL),
- m_Banner(NULL)
+ m_Banner(NULL),
+ m_Level(deskBarCount++)
{
}
CMenuDeskBar::~CMenuDeskBar()
{
+ deskBarCount--;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetWindow(HWND *lphwnd)
@@ -316,7 +325,11 @@
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSite(IUnknown *pUnkSite)
{
+ // Windows closes the bar if this is called when the bar is shown
+
m_Site = pUnkSite;
+
+ IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup,
&m_SubMenuParent));
return S_OK;
}
@@ -468,12 +481,24 @@
int cx = rc.right;
int cy = rc.bottom;
- if (y < 0)
- {
- y = 0;
- }
-
- // if (y+cy > work area height) cy = work area height - y
+ RECT rcWorkArea;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
+
+ int waHeight = rcWorkArea.bottom - rcWorkArea.top;
+
+ if (y < rcWorkArea.top)
+ {
+ y = rcWorkArea.top;
+ }
+
+ if (cy > waHeight)
+ {
+ cy = waHeight;
+ }
+ else if (y + cy > rcWorkArea.bottom)
+ {
+ y = rcWorkArea.bottom - cy;
+ }
this->SetWindowPos(HWND_TOPMOST, x, y, cx, cy, SWP_SHOWWINDOW);
@@ -533,70 +558,87 @@
HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(
DWORD dwSelectType)
{
- CComPtr<IMenuPopup> pmp;
- CComPtr<IDeskBarClient> dbc;
- HRESULT hr;
+ /* As far as I can tell, the submenu hierarchy looks like this:
+
+ The DeskBar's Child is the Band it contains.
+ The DeskBar's Parent is the SID_SMenuPopup of the Site.
+
+ The Band's Child is the IMenuPopup of the child submenu.
+ The Band's Parent is the SID_SMenuPopup of the Site (the DeskBar).
+
+ When the DeskBar receives a selection event:
+ If it requires closing the window, it will notify the Child (Band) using
CancelLevel.
+ If it has to spread upwards (everything but CancelLevel), it will notify the
Parent.
+
+ When the Band receives a selection event, this is where it gets fuzzy:
+ In which cases does it call the Parent? Probably not CancelLevel.
+ In which cases does it call the Child?
+ How does it react to calls?
+
+ */
switch (dwSelectType)
{
case MPOS_EXECUTE:
case MPOS_FULLCANCEL:
case MPOS_CANCELLEVEL:
- hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IMenuPopup,
&pmp));
+
+ _CloseBar();
+
+ if (dwSelectType == MPOS_CANCELLEVEL)
+ return S_OK;
+
+ case MPOS_SELECTLEFT:
+ case MPOS_SELECTRIGHT:
+ case MPOS_CHILDTRACKING:
+ if (m_SubMenuParent)
+ return m_SubMenuParent->OnSelect(dwSelectType);
+ break;
+ }
+
+ return S_OK;
+}
+
+HRESULT CMenuDeskBar::_CloseBar()
+{
+ CComPtr<IDeskBarClient> dbc;
+ HRESULT hr;
+
+ if (m_SubMenuChild)
+ {
+ hr = m_SubMenuChild->OnSelect(MPOS_CANCELLEVEL);
if (FAILED(hr))
return hr;
-
- hr = pmp->OnSelect(MPOS_CANCELLEVEL);
- if (FAILED(hr))
- return hr;
-
- hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
- if (FAILED(hr))
- return hr;
-
- hr = dbc->UIActivateDBC(FALSE);
- if (FAILED(hr))
- return hr;
-
- SetWindowPos(m_hWnd, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOZORDER);
-
- UIActivateIO(FALSE, NULL);
-
- if (dwSelectType == MPOS_CANCELLEVEL)
- break;
-
- case MPOS_SELECTLEFT:
- case MPOS_SELECTRIGHT:
- /*CComPtr<IMenuPopup> pmp;
- hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IMenuPopup,
&pmp));
- if (FAILED(hr))
- return hr;*/
-
- hr = m_SubMenuParent->OnSelect(dwSelectType);
- if (FAILED(hr))
- return hr;
- case MPOS_CHILDTRACKING:
- break;
- }
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(
- IMenuPopup *pmp,
- BOOL fSet)
-{
+ }
+
+ hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
+ if (FAILED(hr))
+ return hr;
+
+ hr = dbc->UIActivateDBC(FALSE);
+ if (FAILED(hr))
+ return hr;
+
+ SetWindowPos(m_hWnd, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOZORDER);
+
+ return UIActivateIO(FALSE, NULL);
+}
+
+HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
+{
+ // Called by the CHILD to notify the parent of the submenu object
+
if (fSet)
{
- m_SubMenuParent = pmp;
+ m_SubMenuChild = pmp;
}
else
{
- if (m_SubMenuParent)
+ if (m_SubMenuChild)
{
- if (SHIsSameObject(pmp, m_SubMenuParent))
+ if (SHIsSameObject(pmp, m_SubMenuChild))
{
- m_SubMenuParent = NULL;
+ m_SubMenuChild = NULL;
}
}
}
Modified: branches/shell-experiments/base/shell/rshell/logging/CMenuSiteWrap.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/logging/CMenuSiteWrap.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/logging/CMenuSiteWrap.cpp [iso-8859-1]
Fri Feb 21 10:00:00 2014
@@ -180,7 +180,7 @@
HRESULT STDMETHODCALLTYPE CMenuSiteWrap::QueryBand(DWORD dwBandID, IDeskBand **ppstb,
DWORD *pdwState, LPWSTR pszName, int cchName)
{
- WrapLogEnter("CMenuSiteWrap<%p>::QueryBand(DWORD dwBandID=%d, IDeskBand
**ppstb=%p, DWORD *pdwState=%p, LPWSTR pszName=%p, int cchName=%p)\n", this,
dwBandID, ppstb, pdwState, pszName, cchName);
+ WrapLogEnter("CMenuSiteWrap<%p>::QueryBand(DWORD dwBandID=%d, IDeskBand
**ppstb=%p, DWORD *pdwState=%p, LPWSTR pszName=%p, int cchName=%d)\n", this,
dwBandID, ppstb, pdwState, pszName, cchName);
HRESULT hr = m_IBandSite->QueryBand(dwBandID, ppstb, pdwState, pszName, cchName);
if (ppstb) WrapLogPost("*ppstb=%p\n", *ppstb);
if (pdwState) WrapLogPost("*pdwState=%d\n", *pdwState);
@@ -190,7 +190,7 @@
HRESULT STDMETHODCALLTYPE CMenuSiteWrap::GetBandObject(DWORD dwBandID, REFIID riid, VOID
**ppv)
{
- WrapLogEnter("CMenuSiteWrap<%p>::GetBandObject(DWORD dwBandID, REFIID
riid, VOID **ppv)\n", this, dwBandID, riid, ppv);
+ WrapLogEnter("CMenuSiteWrap<%p>::GetBandObject(DWORD dwBandID=%d, REFIID
riid=%s, VOID **ppv=%p)\n", this, dwBandID, Wrap(riid), ppv);
HRESULT hr = m_IBandSite->GetBandObject(dwBandID, riid, ppv);
if (ppv) WrapLogPost("*ppv=%p\n", *ppv);
WrapLogExit("CMenuSiteWrap::GetBandObject()", hr);
@@ -201,7 +201,7 @@
{
WrapLogEnter("CMenuSiteWrap<%p>::GetBandSiteInfo(BANDSITEINFO
*pbsinfo=%p)\n", this, pbsinfo);
HRESULT hr = m_IBandSite->GetBandSiteInfo(pbsinfo);
- if (pbsinfo) WrapLogPost("*pbsinfo=%p\n", *pbsinfo);
+ if (pbsinfo) WrapLogPost("*pbsinfo=%s\n", Wrap(*pbsinfo));
WrapLogExit("CMenuSiteWrap::GetBandSiteInfo()", hr);
return hr;
}
@@ -236,7 +236,6 @@
{
WrapLogEnter("CMenuSiteWrap<%p>::SetDeskBarSite(IUnknown
*punkSite=%p)\n", this, punkSite);
HRESULT hr = m_IDeskBarClient->SetDeskBarSite(punkSite);
- if (punkSite) WrapLogPost("*punkSite=%p\n", *punkSite);
WrapLogExit("CMenuSiteWrap::SetDeskBarSite()", hr);
return hr;
}