From: Giannis Adamopoulos Date: Mon, 17 Apr 2017 09:02:49 +0000 (+0000) Subject: [BROWSEUI] -CBandSiteMenu: Add preliminary support for adding and removing bands... X-Git-Tag: ReactOS-0.4.5~89 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=f24e5deac9a2dce0a732fc7a40751ddd4fa93b29;ds=sidebyside [BROWSEUI] -CBandSiteMenu: Add preliminary support for adding and removing bands in the taskbar. If a class was registered in the CATID_DeskBand category it will be shown in the menu and selecting it can add it or remove it from the taskbar. Showing the two built in ones (quick launch and desktop) is not implemented yet. svn path=/trunk/; revision=74345 --- diff --git a/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.cpp b/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.cpp index 36d54a9538d..d323c3dcae6 100644 --- a/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.cpp +++ b/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.cpp @@ -20,58 +20,189 @@ */ #include "shellbars.h" +#include -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 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 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 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 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; } diff --git a/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.h b/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.h index 4c059c35737..d4d27acdc73 100644 --- a/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.h +++ b/reactos/dll/win32/browseui/shellbars/CBandSiteMenu.h @@ -28,7 +28,12 @@ class CBandSiteMenu : public IContextMenu3, public IShellService { - CComPtr m_Owner; + CComPtr m_BandSite; + HDSA m_menuDsa; + HMENU m_hmenu; + + HRESULT CreateMenuPart(); + public: CBandSiteMenu(); ~CBandSiteMenu();