https://git.reactos.org/?p=reactos.git;a=commitdiff;h=37e6151b40178a2cbea3f…
commit 37e6151b40178a2cbea3fc17999eaa35d328666c
Author: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
AuthorDate: Fri Oct 20 16:17:10 2017 +0300
[BROWSEUI] CBandSiteMenu: Implement the Desktop, Quick Launch and New Toolbar menu
items
---
dll/win32/browseui/shellbars/CBandSiteMenu.cpp | 354 +++++++++++++++++++++----
dll/win32/browseui/shellbars/CBandSiteMenu.h | 14 +-
2 files changed, 321 insertions(+), 47 deletions(-)
diff --git a/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
b/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
index 01a31e9f54..300a2ccb40 100644
--- a/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
+++ b/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
@@ -22,9 +22,20 @@
#include "shellbars.h"
#include <strsafe.h>
+/* The menu consists of 3 parts. The first is loaded from the resources,
+ the second is populated with the classes of the CATID_DeskBand comcat
+ and the third part consists of the entries for each CISFBand in the band side.
+ The first 5 ids are reserved for the resource menu, the following ids will be
+ for the CATID_DeskBand classes and the rest for the CISFBands.
+ The ids for the CISFBand menu items are not continuous, in this range
+ each menu id is calculated by adding the band id to the last id for the CATID_DeskBand
range */
+#define FIRST_COMCAT_MENU_ID 0x5
+
CBandSiteMenu::CBandSiteMenu():
- m_menuDsa(NULL),
- m_hmenu(NULL)
+ m_comcatDsa(NULL),
+ m_hmenu(NULL),
+ m_DesktopPidl(NULL),
+ m_QLaunchPidl(NULL)
{
}
@@ -33,14 +44,37 @@ CBandSiteMenu::~CBandSiteMenu()
if (m_hmenu)
DestroyMenu(m_hmenu);
- if (m_menuDsa)
- DSA_Destroy(m_menuDsa);
+ if (m_comcatDsa)
+ DSA_Destroy(m_comcatDsa);
+
+ if (m_DesktopPidl)
+ ILFree(m_DesktopPidl);
+
+ if (m_QLaunchPidl)
+ ILFree(m_QLaunchPidl);
m_BandSite = NULL;
}
+HRESULT WINAPI CBandSiteMenu::FinalConstruct()
+{
+ HRESULT hr = SHGetFolderLocation(0, CSIDL_DESKTOP, NULL, 0, &m_DesktopPidl);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ WCHAR buffer[MAX_PATH];
+ hr = SHGetFolderPathAndSubDirW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0,
L"Microsoft\\Internet Explorer\\Quick Launch", buffer);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
-HRESULT CBandSiteMenu::CreateMenuPart()
+ m_QLaunchPidl = ILCreateFromPathW(buffer);
+ if (m_QLaunchPidl == NULL)
+ return E_FAIL;
+
+ return S_OK;
+}
+
+HRESULT CBandSiteMenu::_CreateMenuPart()
{
WCHAR wszBandName[MAX_PATH];
WCHAR wszBandGUID[MAX_PATH];
@@ -56,16 +90,16 @@ HRESULT CBandSiteMenu::CreateMenuPart()
if (m_hmenu)
DestroyMenu(m_hmenu);
- if (m_menuDsa)
- DSA_Destroy(m_menuDsa);
+ if (m_comcatDsa)
+ DSA_Destroy(m_comcatDsa);
/* 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)
+ m_comcatDsa = DSA_Create(sizeof(GUID), 5);
+ if (!m_comcatDsa)
return E_OUTOFMEMORY;
/* Get the handle of the submenu where the available items will be shown */
@@ -94,8 +128,8 @@ HRESULT CBandSiteMenu::CreateMenuPart()
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);
+ InsertMenu(hmenuToolbars, cBands, MF_BYPOSITION, DSA_GetItemCount(m_comcatDsa) +
FIRST_COMCAT_MENU_ID, wszBandName);
+ DSA_AppendItem(m_comcatDsa, &iter);
cBands++;
}
while (dwRead > 0);
@@ -103,12 +137,197 @@ HRESULT CBandSiteMenu::CreateMenuPart()
return S_OK;
}
+HRESULT CBandSiteMenu::_CreateNewISFBand(HWND hwnd, REFIID riid, void** ppv)
+{
+ WCHAR path[MAX_PATH];
+ WCHAR message[256];
+ BROWSEINFOW bi = { hwnd, NULL, path };
+
+ if (LoadStringW(GetModuleHandleW(L"browseui.dll"), IDS_BROWSEFORNEWTOOLAR,
message, _countof(message)))
+ bi.lpszTitle = message;
+ else
+ bi.lpszTitle = L"Choose a folder";
+
+ LPITEMIDLIST pidlSelected = SHBrowseForFolderW(&bi);
+ if (pidlSelected == NULL)
+ return S_FALSE;
+
+ CComPtr<IShellFolderBand> pISFB;
+ HRESULT hr = CISFBand_CreateInstance(IID_IShellFolderBand, (PVOID*)&pISFB);
+ if (FAILED_UNEXPECTEDLY(hr))
+ goto done;
+
+ hr = pISFB->InitializeSFB(NULL, pidlSelected);
+ if (FAILED_UNEXPECTEDLY(hr))
+ goto done;
+
+ hr = pISFB->QueryInterface(riid, ppv);
+
+done:
+ ILFree(pidlSelected);
+ return hr;
+}
+
+HRESULT CBandSiteMenu::_CreateBuiltInISFBand(UINT uID, REFIID riid, void** ppv)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+
+ pidl = (uID == IDM_TASKBAR_TOOLBARS_DESKTOP) ? m_DesktopPidl : m_QLaunchPidl;
+
+ CComPtr<IShellFolderBand> pISFB;
+ hr = CISFBand_CreateInstance(IID_IShellFolderBand, (PVOID*)&pISFB);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ hr = pISFB->InitializeSFB(NULL, pidl);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ return pISFB->QueryInterface(riid, ppv);
+}
+
+HRESULT CBandSiteMenu::_AddISFBandToMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,
UINT idCmdLast, IUnknown* pBand, DWORD dwBandID, UINT *newMenuId)
+{
+ CComPtr<IShellFolderBand> psfb;
+ HRESULT hr = pBand->QueryInterface(IID_PPV_ARG(IShellFolderBand, &psfb));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ BANDINFOSFB bi = {ISFB_MASK_IDLIST};
+ hr = psfb->GetBandInfoSFB(&bi);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ if (!bi.pidl)
+ return E_OUTOFMEMORY;
+
+ WCHAR buffer[MAX_PATH];
+ hr = ILGetDisplayNameEx(NULL, bi.pidl, buffer, ILGDN_INFOLDER) ? S_OK : E_FAIL;
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ UINT id = idCmdFirst + DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID +
dwBandID;
+ if (id >= idCmdLast)
+ return E_FAIL;
+
+ *newMenuId = id;
+ InsertMenu(hmenu, indexMenu, MF_BYPOSITION, id, buffer);
+ return S_OK;
+}
+
+UINT CBandSiteMenu::_GetMenuIdFromISFBand(IUnknown *pBand)
+{
+ UINT ret = UINT_MAX;
+
+ CComPtr<IShellFolderBand> psfb;
+ HRESULT hr = pBand->QueryInterface(IID_PPV_ARG(IShellFolderBand, &psfb));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return ret;
+
+ BANDINFOSFB bi = {ISFB_MASK_IDLIST};
+ hr = psfb->GetBandInfoSFB(&bi);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return ret;
+
+ CComPtr<IShellFolder> psfDesktop;
+ LPITEMIDLIST pidl = bi.pidl;
+ if (!pidl)
+ return ret;
+
+ if (pidl->mkid.cb == 0)
+ {
+ ret = IDM_TASKBAR_TOOLBARS_DESKTOP;
+ goto done;
+ }
+
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED_UNEXPECTEDLY(hr))
+ goto done;
+
+ hr = psfDesktop->CompareIDs(0, pidl, m_QLaunchPidl);
+ if (FAILED_UNEXPECTEDLY(hr))
+ goto done;
+
+ if (HRESULT_CODE(hr) == 0)
+ ret = IDM_TASKBAR_TOOLBARS_QUICKLAUNCH;
+
+done:
+ if (pidl)
+ ILFree(pidl);
+
+ return ret;
+}
+
+UINT CBandSiteMenu::_GetMenuIdFromBand(CLSID *BandCLSID)
+{
+ /* Try to find the clsid of the band in the dsa */
+ UINT count = DSA_GetItemCount(m_comcatDsa);
+ for (UINT i = 0; i < count; i++)
+ {
+ GUID* pdsaGUID = (GUID*)DSA_GetItemPtr(m_comcatDsa, i);
+ if (IsEqualGUID(*pdsaGUID, *BandCLSID))
+ {
+ /* The index in the dsa is also the index in the menu */
+ return i + FIRST_COMCAT_MENU_ID;
+ }
+ }
+
+ return UINT_MAX;
+}
+
+UINT CBandSiteMenu::_GetBandIdFromClsid(CLSID* pclsid)
+{
+ CComPtr<IPersist> pBand;
+ CLSID BandCLSID;
+ DWORD dwBandID;
+
+ for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID));
uBand++)
+ {
+ if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist,
&pBand))))
+ continue;
+
+ if (FAILED(pBand->GetClassID(&BandCLSID)))
+ continue;
+
+ if (IsEqualGUID(*pclsid, BandCLSID))
+ return dwBandID;
+ }
+
+ return UINT_MAX;
+}
+
+UINT CBandSiteMenu::_GetBandIdForBuiltinISFBand(UINT uID)
+{
+ CComPtr<IPersist> pBand;
+ CLSID BandCLSID;
+ DWORD dwBandID;
+
+ for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID));
uBand++)
+ {
+ if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist,
&pBand))))
+ continue;
+
+ if (FAILED(pBand->GetClassID(&BandCLSID)))
+ continue;
+
+ if (!IsEqualGUID(BandCLSID, CLSID_ISFBand))
+ continue;
+
+ UINT menuID = _GetMenuIdFromISFBand(pBand);
+ if (menuID == uID)
+ return dwBandID;
+ }
+
+ return UINT_MAX;
+}
+
HRESULT STDMETHODCALLTYPE CBandSiteMenu::SetOwner(IUnknown *pOwner)
{
TRACE("CBandSiteMenu::SetOwner(%p, %p)\n", this, pOwner);
/* Cache the menu that will be merged every time QueryContextMenu is called */
- CreateMenuPart();
+ _CreateMenuPart();
return pOwner->QueryInterface(IID_PPV_ARG(IBandSite, &m_BandSite));
}
@@ -119,11 +338,12 @@ HRESULT STDMETHODCALLTYPE CBandSiteMenu::QueryContextMenu(
CComPtr<IPersist> pBand;
CLSID BandCLSID;
DWORD dwBandID;
+ UINT idMax;
TRACE("CBandSiteMenu::QueryContextMenu(%p, %p, %u, %u, %u, 0x%x)\n", this,
hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
/* First Merge the menu with the available bands */
- Shell_MergeMenus(hmenu, m_hmenu, indexMenu, idCmdFirst, idCmdLast, MM_DONTREMOVESEPS
| MM_SUBMENUSHAVEIDS);
+ idMax = Shell_MergeMenus(hmenu, m_hmenu, indexMenu, idCmdFirst, idCmdLast,
MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
HMENU hmenuToolbars = GetSubMenu(hmenu, indexMenu);
@@ -136,63 +356,107 @@ HRESULT STDMETHODCALLTYPE CBandSiteMenu::QueryContextMenu(
if (FAILED(pBand->GetClassID(&BandCLSID)))
continue;
- /* Try to find the clsid of the band in the dsa */
- UINT count = DSA_GetItemCount(m_menuDsa);
- for (UINT i = 0; i < count; i++)
+ UINT menuID;
+ if (IsEqualGUID(BandCLSID, CLSID_ISFBand))
{
- GUID* pdsaGUID = (GUID*)DSA_GetItemPtr(m_menuDsa, i);
- if (memcmp(pdsaGUID, &BandCLSID, sizeof(GUID)) == 0)
+ menuID = _GetMenuIdFromISFBand(pBand);
+ if (menuID == UINT_MAX)
{
- /* The index in the dsa is also the index in the menu */
- CheckMenuItem(hmenuToolbars, i, MF_CHECKED | MF_BYPOSITION);
+ HRESULT hr;
+ hr = _AddISFBandToMenu(hmenuToolbars, 0, idCmdFirst, idCmdLast, pBand,
dwBandID, &menuID);
+ if (SUCCEEDED(hr) && menuID > idMax)
+ idMax = menuID;
+ menuID -= idCmdFirst;
}
}
+ else
+ {
+ menuID = _GetMenuIdFromBand(&BandCLSID);
+ }
+
+ if (menuID != UINT_MAX)
+ CheckMenuItem(hmenuToolbars, menuID + idCmdFirst, MF_CHECKED);
}
- return S_OK;
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idMax - idCmdFirst +1));
}
HRESULT STDMETHODCALLTYPE CBandSiteMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
+ HRESULT hRet;
+ DWORD dwBandID;
+
/* 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;
+ if (uID == IDM_TASKBAR_TOOLBARS_NEW)
+ {
+ CComPtr<IDeskBand> pDeskBand;
+ hRet = _CreateNewISFBand(lpici->hwnd, IID_PPV_ARG(IDeskBand,
&pDeskBand));
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
- /* 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;
- for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID));
uBand++)
+ hRet = m_BandSite->AddBand(pDeskBand);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+
+ return S_OK;
+ }
+ else if (uID > (UINT)DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID )
{
- if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist,
&pBand))))
- continue;
+ dwBandID = uID - (DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID );
- if (FAILED(pBand->GetClassID(&BandCLSID)))
- continue;
+ m_BandSite->RemoveBand(dwBandID);
- if (memcmp(pguidToolbar, &BandCLSID, sizeof(GUID)) == 0)
+ return S_OK;
+ }
+ else if (uID == IDM_TASKBAR_TOOLBARS_DESKTOP || uID ==
IDM_TASKBAR_TOOLBARS_QUICKLAUNCH)
+ {
+ dwBandID = _GetBandIdForBuiltinISFBand(uID);
+ if (dwBandID != UINT_MAX)
{
- /* We found it, remove it */
m_BandSite->RemoveBand(dwBandID);
- return S_OK;
}
+ else
+ {
+ CComPtr<IDeskBand> pDeskBand;
+ hRet = _CreateBuiltInISFBand(uID, IID_PPV_ARG(IDeskBand, &pDeskBand));
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+
+ hRet = m_BandSite->AddBand(pDeskBand);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+ }
+ return S_OK;
}
- /* 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;
+ /* Get the GUID of the item that was clicked */
+ GUID *pguidToolbar = (GUID *)DSA_GetItemPtr(m_comcatDsa, uID -
FIRST_COMCAT_MENU_ID);
+ if (!pguidToolbar)
+ return E_FAIL;
- hRet = m_BandSite->AddBand(pDeskBand);
- if (FAILED_UNEXPECTEDLY(hRet))
- return hRet;
+ /* Try to find if a band with a guid is present. If it is, remove it and return */
+ dwBandID = _GetBandIdFromClsid(pguidToolbar);
+ if (dwBandID != UINT_MAX)
+ {
+ /* We found it, remove it */
+ m_BandSite->RemoveBand(dwBandID);
+ }
+ else
+ {
+ /* It is not present. Add it. */
+ CComPtr<IDeskBand> pDeskBand;
+ hRet = CoCreateInstance(*pguidToolbar, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IDeskBand, &pDeskBand));
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+
+ hRet = m_BandSite->AddBand(pDeskBand);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return hRet;
+ }
return S_OK;
}
diff --git a/dll/win32/browseui/shellbars/CBandSiteMenu.h
b/dll/win32/browseui/shellbars/CBandSiteMenu.h
index d4d27acdc7..f05107b529 100644
--- a/dll/win32/browseui/shellbars/CBandSiteMenu.h
+++ b/dll/win32/browseui/shellbars/CBandSiteMenu.h
@@ -29,14 +29,24 @@ class CBandSiteMenu :
public IShellService
{
CComPtr<IBandSite> m_BandSite;
- HDSA m_menuDsa;
+ HDSA m_comcatDsa;
HMENU m_hmenu;
+ LPITEMIDLIST m_DesktopPidl;
+ LPITEMIDLIST m_QLaunchPidl;
- HRESULT CreateMenuPart();
+ HRESULT _CreateMenuPart();
+ HRESULT _CreateNewISFBand(HWND hwnd, REFIID riid, void** ppv);
+ HRESULT _CreateBuiltInISFBand(UINT uID, REFIID riid, void** ppv);
+ HRESULT _AddISFBandToMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT
idCmdLast, IUnknown* pBand, DWORD dwBandID, UINT *newMenuId);
+ UINT _GetMenuIdFromISFBand(IUnknown *pBand);
+ UINT _GetMenuIdFromBand(CLSID *BandCLSID);
+ UINT _GetBandIdFromClsid(CLSID* pclsid);
+ UINT _GetBandIdForBuiltinISFBand(UINT uID);
public:
CBandSiteMenu();
~CBandSiteMenu();
+ HRESULT WINAPI FinalConstruct();
// *** IShellService methods ***
virtual HRESULT STDMETHODCALLTYPE SetOwner(IUnknown *);