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/rsh... ============================================================================== --- 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/rsh... ============================================================================== --- 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/rsh... ============================================================================== --- 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; }