extern "C"
HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
{
-#if USE_SYSTEM_MENUBAND
- hr = CoCreateInstance(CLSID_MenuBand,
- NULL,
- CLSCTX_INPROC_SERVER,
- riid, ppv);
-#else
- *ppv = NULL;
-
- CMenuBand * site = new CComObject<CMenuBand>();
-
- if (!site)
- return E_OUTOFMEMORY;
-
- HRESULT hr = site->QueryInterface(riid, ppv);
-
- if (FAILED_UNEXPECTEDLY(hr))
- site->Release();
-
- return hr;
-#endif
+ return ShellObjectCreator<CMenuBand>(riid, ppv);
}
CMenuBand::CMenuBand() :
m_hotBar(NULL),
m_hotItem(-1),
m_popupBar(NULL),
- m_popupItem(-1)
+ m_popupItem(-1),
+ m_Show(FALSE),
+ m_shellBottom(FALSE),
+ m_trackedPopup(NULL),
+ m_trackedHwnd(NULL)
{
m_focusManager = CMenuFocusManager::AcquireManager();
}
if (m_SFToolbar)
delete m_SFToolbar;
+
+ if (m_hmenu)
+ DestroyMenu(m_hmenu);
}
HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
return E_INVALIDARG;
if (ppsmc)
+ {
+ m_psmc->AddRef();
*ppsmc = m_psmc;
+ }
if (puId)
*puId = m_uId;
BOOL created = FALSE;
+ if (m_hmenu)
+ {
+ DestroyMenu(m_hmenu);
+ m_hmenu = NULL;
+ }
+
if (m_staticToolbar == NULL)
{
m_staticToolbar = new CMenuStaticToolbar(this);
return m_site->QueryInterface(riid, ppvSite);
}
-HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(
- HWND *phwnd)
+HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(HWND *phwnd)
{
if (m_SFToolbar != NULL)
return m_SFToolbar->GetWindow(phwnd);
if (m_staticToolbar != NULL)
return m_staticToolbar->GetWindow(phwnd);
+ if (phwnd) *phwnd = NULL;
+
return E_FAIL;
}
int syStatic = maxStatic.cy;
int syShlFld = sy - syStatic;
- if (m_SFToolbar)
+ if (m_shellBottom)
{
- m_SFToolbar->SetPosSize(
- prc->left,
- prc->top,
- prc->right - prc->left,
- syShlFld);
+ if (m_SFToolbar)
+ {
+ m_SFToolbar->SetPosSize(
+ prc->left,
+ prc->top + syStatic,
+ prc->right - prc->left,
+ syShlFld);
+ }
+ if (m_staticToolbar)
+ {
+ m_staticToolbar->SetPosSize(
+ prc->left,
+ prc->top,
+ prc->right - prc->left,
+ syStatic);
+ }
}
- if (m_staticToolbar)
+ else // shell menu on top
{
- m_staticToolbar->SetPosSize(
- prc->left,
- prc->top + syShlFld,
- prc->right - prc->left,
- syStatic);
+ if (m_SFToolbar)
+ {
+ m_SFToolbar->SetPosSize(
+ prc->left,
+ prc->top,
+ prc->right - prc->left,
+ syShlFld);
+ }
+ if (m_staticToolbar)
+ {
+ m_staticToolbar->SetPosSize(
+ prc->left,
+ prc->top + syShlFld,
+ prc->right - prc->left,
+ syStatic);
+ }
}
return S_OK;
}
+
HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
DWORD dwBandID,
DWORD dwViewMode,
if (m_dwFlags & SMINIT_VERTICAL)
{
- pdbi->ptMinSize.x = max(minStatic.cx, minStatic.cx) + 20;
- pdbi->ptMinSize.y = minStatic.cy + minStatic.cy;
+ pdbi->ptMinSize.x = max(minStatic.cx, minShlFld.cx) + 20;
+ pdbi->ptMinSize.y = minStatic.cy + minShlFld.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->ptMinSize.x = minStatic.cx + minShlFld.cx;
+ pdbi->ptMinSize.y = max(minStatic.cy, minShlFld.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.x = max(intStatic.cx, intShlFld.cx);
pdbi->ptIntegral.y = max(intStatic.cy, intShlFld.cy);
pdbi->ptActual = pdbi->ptMinSize;
{
HRESULT hr = S_OK;
+ if (m_Show == fShow)
+ return S_OK;
+
+ m_Show = fShow;
+
if (m_staticToolbar != NULL)
{
hr = m_staticToolbar->ShowWindow(fShow);
HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
{
+ if (m_subMenuChild)
+ {
+ m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ }
+
+ if (m_subMenuChild)
+ {
+ DbgPrint("Child object should have removed itself.\n");
+ }
+
ShowDW(FALSE);
if (m_staticToolbar != NULL)
- return m_staticToolbar->Close();
+ {
+ m_staticToolbar->Close();
+ }
if (m_SFToolbar != NULL)
- return m_SFToolbar->Close();
+ {
+ m_SFToolbar->Close();
+ }
+
+ if (m_site) m_site.Release();
+ if (m_subMenuChild) m_subMenuChild.Release();
+ if (m_subMenuParent) m_subMenuParent.Release();
+ if (m_childBand) m_childBand.Release();
+ if (m_parentBand) m_parentBand.Release();
return S_OK;
}
{
return S_FALSE;
}
+ else if (nCmdID == 5) // select an item
+ {
+ if (nCmdexecopt == 0) // first
+ {
+ _KeyboardItemChange(VK_HOME);
+ }
+ else // last
+ {
+ _KeyboardItemChange(VK_END);
+ }
+ return S_FALSE;
+ }
return S_FALSE;
}
HRESULT CMenuBand::_IsPopup()
{
- return m_subMenuParent ? S_OK : S_FALSE;
+ return !(m_dwFlags & SMINIT_VERTICAL);
}
HRESULT CMenuBand::_IsTracking()
HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
{
+ CComPtr<IMenuPopup> child = m_subMenuChild;
+
m_subMenuChild = NULL;
+
+ if (child)
+ {
+ IUnknown_SetSite(child, NULL);
+ child.Release();
+ }
if (!punkClient)
{
return S_OK;
}
- HRESULT hr = punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
-
- return hr;
+ return punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
}
HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
{
// HACK, so I can test for a submenu in the DeskBar
- if (ppunkClient)
+ if (!ppunkClient)
+ return E_POINTER;
+ *ppunkClient = NULL;
+
+ if (m_subMenuChild)
{
- if (m_subMenuChild)
- *ppunkClient = m_subMenuChild;
- else
- *ppunkClient = NULL;
+ m_subMenuChild->AddRef();
+ *ppunkClient = m_subMenuChild;
}
+
return S_OK;
}
if (FAILED_UNEXPECTEDLY(hr))
return hr;
+ m_shellBottom = (dwFlags & SMSET_BOTTOM) != 0;
+
if (m_site)
{
HWND hwndParent;
UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
HWND hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
+ m_trackedPopup = popup;
+ m_trackedHwnd = hwnd;
+
m_focusManager->PushTrackedPopup(popup);
::TrackPopupMenuEx(popup, flags, x, y, hwnd, ¶ms);
m_focusManager->PopTrackedPopup(popup);
+ m_trackedPopup = NULL;
+ m_trackedHwnd = NULL;
+
_DisableMouseTrack(FALSE);
return S_OK;
HWND hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
+ m_focusManager->PushTrackedPopup(popup);
+
TRACE("Before Tracking\n");
uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, hwnd, NULL);
+ m_focusManager->PopTrackedPopup(popup);
+
if (uCommand != 0)
{
TRACE("Before InvokeCommand\n");
if (!tb)
{
// If no hot item was selected choose the appropriate toolbar
- if (change == VK_UP)
+ if (change == VK_UP || change == VK_END)
{
if (m_staticToolbar)
tb = m_staticToolbar;
else
tb = m_SFToolbar;
}
- else if (change == VK_DOWN)
+ else if (change == VK_DOWN || change == VK_HOME)
{
if (m_SFToolbar)
tb = m_SFToolbar;
HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
{
+ CComPtr<CMenuBand> safeThis = this;
HRESULT hr;
if (m_dwFlags & SMINIT_VERTICAL)
switch (changeType)
{
case MPOS_EXECUTE:
- m_hotBar->ExecuteItem(m_hotItem);
+ {
+ CMenuToolbarBase * tb = m_hotBar;
+ int item = m_hotItem;
+ tb->PrepareExecuteItem(item);
+ if (m_subMenuParent)
+ {
+ m_subMenuParent->OnSelect(changeType);
+ }
+ TRACE("Menu closed, executing item...\n");
+ tb->ExecuteItem();
break;
-
+ }
case MPOS_SELECTLEFT:
if (m_parentBand && m_parentBand->_IsPopup()==S_FALSE)
return m_parentBand->_MenuItemHotTrack(VK_LEFT);
return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
case MPOS_SELECTRIGHT:
- if (m_hotBar && m_hotItem >= 0 && m_hotBar->PopupItem(m_hotItem) == S_OK)
+ if (m_hotBar && m_hotItem >= 0 && m_hotBar->PopupItem(m_hotItem, TRUE) == S_OK)
return S_FALSE;
if (m_parentBand)
return m_parentBand->_MenuItemHotTrack(VK_RIGHT);
return S_OK;
return m_subMenuParent->OnSelect(changeType);
}
+
+ return S_OK;
}
HRESULT CMenuBand::_CancelCurrentPopup()
{
- if (!m_subMenuChild)
- return S_FALSE;
+ if (m_subMenuChild)
+ {
+ HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ return hr;
+ }
- HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
- return hr;
+ if (m_trackedPopup)
+ {
+ ::SendMessage(m_trackedHwnd, WM_CANCELMODE, 0, 0);
+ return S_OK;
+ }
+
+ return S_FALSE;
}
-HRESULT CMenuBand::_OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL * pExclude)
+HRESULT CMenuBand::_OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL * pExclude, BOOL keyInitiated)
{
HRESULT hr = 0;
- IBandSite* pBandSite;
- IDeskBar* pDeskBar;
+ CComPtr<IBandSite> pBandSite;
+ CComPtr<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 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;
else
IUnknown_SetSite(popup, m_site);
- popup->Popup(pAt, pExclude, MPPF_RIGHT);
+ DWORD flags = MPPF_RIGHT;
+
+ if (keyInitiated && m_dwFlags & SMINIT_VERTICAL)
+ flags |= MPPF_INITIALSELECT;
+
+ popup->Popup(pAt, pExclude, flags);
return S_OK;
}
return hr;
}
+HRESULT CMenuBand::_MenuBarMouseDown(HWND hwnd, INT item)
+{
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK)
+ m_staticToolbar->MenuBarMouseDown(item);
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK)
+ m_SFToolbar->MenuBarMouseDown(item);
+ return S_OK;
+}
+
+HRESULT CMenuBand::_MenuBarMouseUp(HWND hwnd, INT item)
+{
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hwnd) == S_OK)
+ m_staticToolbar->MenuBarMouseUp(item);
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hwnd) == S_OK)
+ m_SFToolbar->MenuBarMouseUp(item);
+ return S_OK;
+}
+
+HRESULT CMenuBand::_HasSubMenu()
+{
+ return m_popupBar ? S_OK : S_FALSE;
+}
+
HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
{
UNIMPLEMENTED;
HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
{
- UNIMPLEMENTED;
- return S_OK;
+ if (m_popupBar)
+ return S_OK;
+ return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
{
- UNIMPLEMENTED;
- return S_OK;
+ // TODO: Alt down -> toggle menu focus
+ return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()