#undef UNIMPLEMENTED
-#define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
+#define UNIMPLEMENTED TRACE("%s is UNIMPLEMENTED!\n", __FUNCTION__)
extern "C"
HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
{
- *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;
+ 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;
HWND hwnd,
DWORD dwFlags)
{
- DbgPrint("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu, hwnd, dwFlags);
+ TRACE("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu, hwnd, dwFlags);
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;
HRESULT CMenuBand::_TrackSubMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
{
TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
+ UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
+ HWND hwnd = m_menuOwner ? m_menuOwner : m_topLevelWindow;
- UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
+ m_trackedPopup = popup;
+ m_trackedHwnd = hwnd;
m_focusManager->PushTrackedPopup(popup);
- if (m_menuOwner)
- {
- ::TrackPopupMenuEx(popup, flags, x, y, m_menuOwner, ¶ms);
- }
- else
- {
- ::TrackPopupMenuEx(popup, flags, x, y, m_topLevelWindow, ¶ms);
- }
+ ::TrackPopupMenuEx(popup, flags, x, y, hwnd, ¶ms);
m_focusManager->PopTrackedPopup(popup);
+ m_trackedPopup = NULL;
+ m_trackedHwnd = NULL;
+
_DisableMouseTrack(FALSE);
return S_OK;
if (popup == NULL)
return E_FAIL;
+ TRACE("Before Query\n");
hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
if (FAILED_UNEXPECTEDLY(hr))
{
+ TRACE("Query failed\n");
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;
+ TRACE("Before Tracking\n");
+ uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, hwnd, NULL);
+
+ m_focusManager->PopTrackedPopup(popup);
- CMINVOKECOMMANDINFO cmi = { 0 };
- cmi.cbSize = sizeof(cmi);
- cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
- cmi.hwnd = hwnd;
- hr = contextMenu->InvokeCommand(&cmi);
+ if (uCommand != 0)
+ {
+ TRACE("Before InvokeCommand\n");
+ CMINVOKECOMMANDINFO cmi = { 0 };
+ cmi.cbSize = sizeof(cmi);
+ cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+ cmi.hwnd = hwnd;
+ hr = contextMenu->InvokeCommand(&cmi);
+ }
+ else
+ {
+ TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
+ hr = S_FALSE;
+ }
DestroyMenu(popup);
return hr;
if (m_hotBar == tb && m_hotItem == id)
return S_FALSE;
- DbgPrint("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, tb, id);
+ TRACE("Hot item changed from %p %p, to %p %p\n", m_hotBar, m_hotItem, tb, id);
_KillPopupTimers();
HRESULT CMenuBand::_ChangePopupItem(CMenuToolbarBase * tb, INT id)
{
- DbgPrint("Popup item changed from %p %p, to %p %p\n", m_popupBar, m_popupItem, tb, id);
+ TRACE("Popup item changed from %p %p, to %p %p\n", m_popupBar, m_popupItem, tb, id);
m_popupBar = tb;
m_popupItem = id;
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;
+ // If no hot item was selected choose the appropriate toolbar
+ if (change == VK_UP || change == VK_END)
+ {
+ if (m_staticToolbar)
+ tb = m_staticToolbar;
+ else
+ tb = m_SFToolbar;
+ }
+ else if (change == VK_DOWN || change == VK_HOME)
+ {
+ if (m_SFToolbar)
+ tb = m_SFToolbar;
+ else
+ tb = m_staticToolbar;
+ }
}
// Ask the first toolbar to change
return hr;
// Select the second toolbar based on the first
- if (tb == m_SFToolbar)
+ if (tb == m_SFToolbar && m_staticToolbar)
tb = m_staticToolbar;
- else
+ else if (m_SFToolbar)
tb = m_SFToolbar;
if (!tb)
return hr;
// Ask the second toolbar to change
- return tb->KeyboardItemChange(change == VK_DOWN ? VK_END : VK_HOME);
+ return tb->KeyboardItemChange(change == VK_DOWN ? VK_HOME : VK_END);
}
HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
{
+ CComPtr<CMenuBand> safeThis = this;
HRESULT hr;
-
if (m_dwFlags & SMINIT_VERTICAL)
{
switch (changeType)
else
{
// In horizontal menubars, left/right are equivalent to vertical's up/down
- switch(changeType)
+ switch (changeType)
{
case VK_LEFT:
hr = _KeyboardItemChange(VK_UP);
switch (changeType)
{
+ case MPOS_EXECUTE:
+ {
+ 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);
+ if (m_subMenuChild)
+ return m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
if (!m_subMenuParent)
- {
- if (m_subMenuChild)
- return m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
return S_OK;
- }
return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
case MPOS_SELECTRIGHT:
- if (m_hotBar && m_hotItem >= 0)
- {
- if (m_hotBar->PopupItem(m_hotItem) == S_OK)
- return S_FALSE;
- }
+ 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);
if (!m_subMenuParent)
return S_OK;
return m_subMenuParent->OnSelect(MPOS_SELECTRIGHT);
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,
#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,
#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;
m_subMenuChild = popup;
-
+
if (m_subMenuParent)
IUnknown_SetSite(popup, m_subMenuParent);
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()