*/
#include "shellbars.h"
+#include <strsafe.h>
-CBandSiteMenu::CBandSiteMenu()
+#define IDM_DESKBAND_BEGINCUSTOM 0x10
+#define IDM_DESKBAND_ENDCUSTOM 0x25
+
+CBandSiteMenu::CBandSiteMenu():
+ m_menuDsa(NULL),
+ m_hmenu(NULL)
{
}
CBandSiteMenu::~CBandSiteMenu()
{
+ if (m_hmenu)
+ DestroyMenu(m_hmenu);
+
+ if (m_menuDsa)
+ DSA_Destroy(m_menuDsa);
+
+ m_BandSite = NULL;
+}
+
+
+HRESULT CBandSiteMenu::CreateMenuPart()
+{
+ WCHAR wszBandName[MAX_PATH];
+ WCHAR wszBandGUID[MAX_PATH];
+ WCHAR wRegKey[MAX_PATH];
+ UINT cBands;
+ DWORD dwDataSize;
+ CATID category = CATID_DeskBand;
+ HMENU hmenuToolbars;
+ DWORD dwRead;
+ CComPtr<IEnumGUID> pEnumGUID;
+ HRESULT hr;
+
+ if (m_hmenu)
+ DestroyMenu(m_hmenu);
+
+ if (m_menuDsa)
+ DSA_Destroy(m_menuDsa);
+
+ /* Load the template we will fill in */
+ m_hmenu = LoadMenuW(GetModuleHandleW(L"browseui.dll"), MAKEINTRESOURCEW(IDM_TASKBAR_TOOLBARS));
+ if (!m_hmenu)
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ m_menuDsa = DSA_Create(sizeof(GUID), 5);
+ if (!m_menuDsa)
+ return E_OUTOFMEMORY;
+
+ /* Get the handle of the submenu where the available items will be shown */
+ hmenuToolbars = GetSubMenu(m_hmenu, 0);
+
+ /* Create the category enumerator */
+ hr = SHEnumClassesOfCategories(1, &category, 0, NULL, &pEnumGUID);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ /* Enumerate the classes in the CATID_DeskBand category */
+ cBands = 0;
+ do
+ {
+ GUID iter;
+ pEnumGUID->Next(1, &iter, &dwRead);
+ if (!dwRead)
+ continue;
+
+ if (!StringFromGUID2(iter, wszBandGUID, MAX_PATH))
+ continue;
+
+ /* Get the band name */
+ StringCchPrintfW(wRegKey, MAX_PATH, L"CLSID\\%s", wszBandGUID);
+ dwDataSize = MAX_PATH;
+ SHGetValue(HKEY_CLASSES_ROOT, wRegKey, NULL, NULL, wszBandName, &dwDataSize);
+
+ /* Insert it */
+ InsertMenu(hmenuToolbars, cBands, MF_BYPOSITION, DSA_GetItemCount(m_menuDsa), wszBandName);
+ DSA_AppendItem(m_menuDsa, &iter);
+ cBands++;
+ }
+ while (dwRead > 0);
+
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE CBandSiteMenu::SetOwner(IUnknown *pOwner)
{
TRACE("CBandSiteMenu::SetOwner(%p, %p)\n", this, pOwner);
- m_Owner = pOwner;
- return S_OK;
+
+ /* Cache the menu that will be merged every time QueryContextMenu is called */
+ CreateMenuPart();
+
+ return pOwner->QueryInterface(IID_PPV_ARG(IBandSite, &m_BandSite));
}
HRESULT STDMETHODCALLTYPE CBandSiteMenu::QueryContextMenu(
HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
- BOOL ret;
- WCHAR buffer[100];
+ CComPtr<IPersist> pBand;
+ CLSID BandCLSID;
+ DWORD dwBandID;
+ UINT uBand = 0;
TRACE("CBandSiteMenu::QueryContextMenu(%p, %p, %u, %u, %u, 0x%x)\n", this, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
- HMENU hm = LoadMenuW(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDM_TASKBAR_TOOLBARS));
- if (!hm)
- return HRESULT_FROM_WIN32(GetLastError());
+ /* First Merge the menu with the available bands */
+ Shell_MergeMenus(hmenu, m_hmenu, indexMenu, idCmdFirst, idCmdLast, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
- MENUITEMINFOW mii = { 0 };
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU;
- ret = GetMenuItemInfoW(hm, 0, TRUE, &mii);
- if (!hm)
- return HRESULT_FROM_WIN32(GetLastError());
+ HMENU hmenuToolbars = GetSubMenu(hmenu, indexMenu);
- mii.dwTypeData = buffer;
- mii.cch = mii.cch + 1;
+ /* Enumerate all present bands and mark them as checked in the menu */
+ while (SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)))
+ {
+ if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &pBand))))
+ continue;
- ret = GetMenuItemInfoW(hm, 0, TRUE, &mii);
- if (!hm)
- return HRESULT_FROM_WIN32(GetLastError());
+ if (FAILED(pBand->GetClassID(&BandCLSID)))
+ continue;
- ret = InsertMenuItemW(hmenu, 0, TRUE, &mii);
+ /* Try to find the clsid of the band in the dsa */
+ UINT count = DSA_GetItemCount(m_menuDsa);
+ for (UINT i = 0; i < count; i++)
+ {
+ GUID* pdsaGUID = (GUID*)DSA_GetItemPtr(m_menuDsa, i);
+ if (memcmp(pdsaGUID, &BandCLSID, sizeof(GUID)) == 0)
+ {
+ /* The index in the dsa is also the index in the menu */
+ CheckMenuItem(hmenuToolbars, i, MF_CHECKED | MF_BYPOSITION);
+ }
+ }
- RemoveMenu(hm, 0, MF_BYPOSITION);
+ uBand++;
+ }
- return E_NOTIMPL;
+ return S_OK;
}
HRESULT STDMETHODCALLTYPE CBandSiteMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
- FIXME("CBandSiteMenu::InvokeCommand is UNIMPLEMENTED (%p, %p)\n", this, lpici);
+ /* FIXME: do we need to handle this and how? */
+ if (HIWORD(lpici->lpVerb) != NULL)
+ return E_FAIL;
+
+ /* Get the GUID of the item that was clicked */
+ UINT uID = LOWORD(lpici->lpVerb);
+ GUID *pguidToolbar = (GUID *)DSA_GetItemPtr(m_menuDsa, uID);
+ if (!pguidToolbar)
+ return E_FAIL;
+
+ /* Try to find if a band with a guid is present. If it is remove it and return */
+ CComPtr<IPersist> pBand;
+ CLSID BandCLSID;
+ DWORD dwBandID;
+ UINT uBand = 0;
+ while (SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)))
+ {
+ if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &pBand))))
+ continue;
+
+ if (FAILED(pBand->GetClassID(&BandCLSID)))
+ continue;
+
+ if (memcmp(pguidToolbar, &BandCLSID, sizeof(GUID)) == 0)
+ {
+ /* We found it, remove it */
+ m_BandSite->RemoveBand(dwBandID);
+ return S_OK;
+ }
+
+ uBand++;
+ }
+
+ /* It is not present. Add it. */
+ CComPtr<IDeskBand> pDeskBand;
+ HRESULT hRet = CoCreateInstance(*pguidToolbar, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDeskBand, &pDeskBand));
+ if (FAILED(hRet))
+ return hRet;
+
+ hRet = m_BandSite->AddBand(pDeskBand);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+
return S_OK;
}