diff --git a/base/shell/rshell/CMakeLists.txt b/base/shell/rshell/CMakeLists.txt index 7bb3eaa9139..276a4c1c81e 100644 --- a/base/shell/rshell/CMakeLists.txt +++ b/base/shell/rshell/CMakeLists.txt @@ -13,6 +13,7 @@ list(APPEND SOURCE CMenuFocusManager.cpp CMenuSite.cpp CMenuToolbars.cpp + CMergedFolder.cpp CStartMenu.cpp misc.cpp wraplog.cpp diff --git a/base/shell/rshell/CMenuBand.cpp b/base/shell/rshell/CMenuBand.cpp index 7afd5f3aa0b..5e89d7f4510 100644 --- a/base/shell/rshell/CMenuBand.cpp +++ b/base/shell/rshell/CMenuBand.cpp @@ -709,6 +709,8 @@ HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wPa break; } + cdraw->iListGap += 4; + *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only return S_OK; @@ -903,6 +905,7 @@ HRESULT CMenuBand::_OnPopupSubMenu(INT popupItem, IMenuPopup * popup, POINTL * p if (popup) { IUnknown_SetSite(popup, m_subMenuParent); + popup->Popup(pAt, pExclude, MPPF_RIGHT); } if (m_staticToolbar) m_staticToolbar->InvalidateDraw(); diff --git a/base/shell/rshell/CMenuBand.h b/base/shell/rshell/CMenuBand.h index 7e19ee50447..daf5f03e809 100644 --- a/base/shell/rshell/CMenuBand.h +++ b/base/shell/rshell/CMenuBand.h @@ -25,7 +25,6 @@ class CMenuSFToolbar; class CMenuFocusManager; class CMenuBand : - public CComCoClass, public CComObjectRootEx, public IDeskBand, public IObjectWithSite, diff --git a/base/shell/rshell/CMenuDeskBar.h b/base/shell/rshell/CMenuDeskBar.h index 4665f8265d6..6512aa19478 100644 --- a/base/shell/rshell/CMenuDeskBar.h +++ b/base/shell/rshell/CMenuDeskBar.h @@ -25,9 +25,8 @@ typedef CWinTraits< > CMenuWinTraits; class CMenuDeskBar : - public CWindowImpl, - public CComCoClass, public CComObjectRootEx, + public CWindowImpl, public IOleCommandTarget, public IServiceProvider, public IInputObjectSite, diff --git a/base/shell/rshell/CMenuToolbars.cpp b/base/shell/rshell/CMenuToolbars.cpp index 030ea983521..61fa88a9338 100644 --- a/base/shell/rshell/CMenuToolbars.cpp +++ b/base/shell/rshell/CMenuToolbars.cpp @@ -75,11 +75,12 @@ HRESULT CMenuToolbarBase::UpdateImageLists() if (m_menuBand->UseBigIcons()) { shiml = SHIL_LARGE; - SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(0, 0)); + SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 0)); } else { shiml = SHIL_SMALL; + SendMessageW(m_hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(4, 4)); } IImageList * piml; diff --git a/base/shell/rshell/CMergedFolder.cpp b/base/shell/rshell/CMergedFolder.cpp new file mode 100644 index 00000000000..7d4a8fe5d9b --- /dev/null +++ b/base/shell/rshell/CMergedFolder.cpp @@ -0,0 +1,337 @@ +/* + * Shell Menu Site + * + * Copyright 2014 David Quintana + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "precomp.h" +#include +#include + +#include "CMergedFolder.h" + +WINE_DEFAULT_DEBUG_CHANNEL(CMergedFolder); + +class CEnumMergedFolder : + public CComObjectRootEx, + public IEnumIDList +{ +private: + CComPtr m_UserLocal; + CComPtr m_AllUSers; + BOOL m_FirstDone; + +public: + CEnumMergedFolder() : m_UserLocal(NULL), m_AllUSers(NULL), m_FirstDone(FALSE) {} + ~CEnumMergedFolder() {} + + DECLARE_NOT_AGGREGATABLE(CEnumMergedFolder) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CEnumMergedFolder) + COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) + END_COM_MAP() + + HRESULT Begin(HWND hwndOwner, SHCONTF flags, IShellFolder * userLocal, IShellFolder * allUSers) + { + HRESULT hr; + hr = userLocal->EnumObjects(hwndOwner, flags, &m_UserLocal); + if (FAILED(hr)) + return hr; + hr = userLocal->EnumObjects(hwndOwner, flags, &m_AllUSers); + if (FAILED(hr)) + { + m_UserLocal = NULL; + return hr; + } + m_FirstDone = FALSE; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE Next( + ULONG celt, + LPITEMIDLIST *rgelt, + ULONG *pceltFetched) + { + HRESULT hr; + + *pceltFetched = 0; + + if (!m_FirstDone) + { + hr = m_UserLocal->Next(celt, rgelt, pceltFetched); + if (FAILED(hr)) + return hr; + if (hr == S_FALSE) + m_FirstDone = true; + if (celt < 2) + return hr; + } + + DWORD offset = *pceltFetched; + if (*pceltFetched < celt) + { + rgelt += *pceltFetched; + celt = (*pceltFetched - celt); + *pceltFetched = 0; + } + + hr = m_UserLocal->Next(celt, rgelt, pceltFetched); + if (FAILED(hr)) + return hr; + + *pceltFetched += offset; + return hr; + } + + virtual HRESULT STDMETHODCALLTYPE Skip( + ULONG celt) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Reset( + ) + { + if (m_FirstDone) + m_AllUSers->Reset(); + return m_UserLocal->Reset(); + } + + virtual HRESULT STDMETHODCALLTYPE Clone( + IEnumIDList **ppenum) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } +}; + +extern "C" +HRESULT CMergedFolder_Constructor(IShellFolder* userLocal, IShellFolder* allUsers, REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + + CMergedFolder * fld = new CComObject(); + + if (!fld) + return E_OUTOFMEMORY; + + HRESULT hr; + + hr = fld->_SetSources(userLocal, allUsers); + + hr = fld->QueryInterface(riid, ppv); + if (FAILED(hr)) + fld->Release(); + + return hr; +} + +HRESULT CMergedFolder::_SetSources(IShellFolder* userLocal, IShellFolder* allUsers) +{ + m_UserLocal = userLocal; + m_AllUSers = allUsers; + return S_OK; +} + +// IShellFolder +HRESULT STDMETHODCALLTYPE CMergedFolder::ParseDisplayName( + HWND hwndOwner, + LPBC pbcReserved, + LPOLESTR lpszDisplayName, + ULONG *pchEaten, + LPITEMIDLIST *ppidl, + ULONG *pdwAttributes) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::EnumObjects( + HWND hwndOwner, + SHCONTF grfFlags, + IEnumIDList **ppenumIDList) +{ + CEnumMergedFolder * merged = new CComObject(); + *ppenumIDList = merged; + return merged->Begin(hwndOwner, grfFlags, m_UserLocal, m_AllUSers); +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject( + LPCITEMIDLIST pidl, + LPBC pbcReserved, + REFIID riid, + void **ppvOut) +{ + HRESULT hr; + + hr = m_UserLocal->BindToObject(pidl, pbcReserved, riid, ppvOut); + if (SUCCEEDED(hr)) + return hr; + + hr = m_AllUSers->BindToObject(pidl, pbcReserved, riid, ppvOut); + + return hr; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::BindToStorage( + LPCITEMIDLIST pidl, + LPBC pbcReserved, + REFIID riid, + void **ppvObj) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::CompareIDs( + LPARAM lParam, + LPCITEMIDLIST pidl1, + LPCITEMIDLIST pidl2) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::CreateViewObject( + HWND hwndOwner, + REFIID riid, + void **ppvOut) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetAttributesOf( + UINT cidl, + LPCITEMIDLIST *apidl, + SFGAOF *rgfInOut) +{ + HRESULT hr; + + hr = m_UserLocal->GetAttributesOf(cidl, apidl, rgfInOut); + if (SUCCEEDED(hr)) + return hr; + + hr = m_AllUSers->GetAttributesOf(cidl, apidl, rgfInOut); + + return hr; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf( + HWND hwndOwner, + UINT cidl, + LPCITEMIDLIST *apidl, + REFIID riid, + UINT *prgfInOut, + void **ppvOut) +{ + HRESULT hr; + + hr = m_UserLocal->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); + if (SUCCEEDED(hr)) + return hr; + + hr = m_AllUSers->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); + + return hr; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf( + LPCITEMIDLIST pidl, + SHGDNF uFlags, + STRRET *lpName) +{ + HRESULT hr; + + hr = m_UserLocal->GetDisplayNameOf(pidl, uFlags, lpName); + if (SUCCEEDED(hr)) + return hr; + + hr = m_AllUSers->GetDisplayNameOf(pidl, uFlags, lpName); + + return hr; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::SetNameOf( + HWND hwnd, + LPCITEMIDLIST pidl, + LPCOLESTR lpszName, + SHGDNF uFlags, + LPITEMIDLIST *ppidlOut) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// IShellFolder2 +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultSearchGUID( + GUID *lpguid) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::EnumSearches( + IEnumExtraSearch **ppenum) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumn( + DWORD dwReserved, + ULONG *pSort, + ULONG *pDisplay) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumnState( + UINT iColumn, + SHCOLSTATEF *pcsFlags) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsEx( + LPCITEMIDLIST pidl, + const SHCOLUMNID *pscid, + VARIANT *pv) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsOf( + LPCITEMIDLIST pidl, + UINT iColumn, + SHELLDETAILS *psd) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CMergedFolder::MapColumnToSCID( + UINT iColumn, + SHCOLUMNID *pscid) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} \ No newline at end of file diff --git a/base/shell/rshell/CMergedFolder.h b/base/shell/rshell/CMergedFolder.h new file mode 100644 index 00000000000..d60327f96c3 --- /dev/null +++ b/base/shell/rshell/CMergedFolder.h @@ -0,0 +1,135 @@ +/* + * Shell Menu Site + * + * Copyright 2014 David Quintana + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#pragma once + +class CMergedFolder : + public CComObjectRootEx, + public IShellFolder2 +{ +private: + CComPtr m_UserLocal; + CComPtr m_AllUSers; + +public: + CMergedFolder() {} + ~CMergedFolder() {} + + HRESULT _SetSources(IShellFolder* userLocal, IShellFolder* allUSers); + + DECLARE_NOT_AGGREGATABLE(CMergedFolder) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CMergedFolder) + COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2) + COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder) + END_COM_MAP() + + // IShellFolder + virtual HRESULT STDMETHODCALLTYPE ParseDisplayName( + HWND hwndOwner, + LPBC pbcReserved, + LPOLESTR lpszDisplayName, + ULONG *pchEaten, + LPITEMIDLIST *ppidl, + ULONG *pdwAttributes); + + virtual HRESULT STDMETHODCALLTYPE EnumObjects( + HWND hwndOwner, + SHCONTF grfFlags, + IEnumIDList **ppenumIDList); + + virtual HRESULT STDMETHODCALLTYPE BindToObject( + LPCITEMIDLIST pidl, + LPBC pbcReserved, + REFIID riid, + void **ppvOut); + + virtual HRESULT STDMETHODCALLTYPE BindToStorage( + LPCITEMIDLIST pidl, + LPBC pbcReserved, + REFIID riid, + void **ppvObj); + + virtual HRESULT STDMETHODCALLTYPE CompareIDs( + LPARAM lParam, + LPCITEMIDLIST pidl1, + LPCITEMIDLIST pidl2); + + virtual HRESULT STDMETHODCALLTYPE CreateViewObject( + HWND hwndOwner, + REFIID riid, + void **ppvOut); + + virtual HRESULT STDMETHODCALLTYPE GetAttributesOf( + UINT cidl, + LPCITEMIDLIST *apidl, + SFGAOF *rgfInOut); + + virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf( + HWND hwndOwner, + UINT cidl, + LPCITEMIDLIST *apidl, + REFIID riid, + UINT *prgfInOut, + void **ppvOut); + + virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf( + LPCITEMIDLIST pidl, + SHGDNF uFlags, + STRRET *lpName); + + virtual HRESULT STDMETHODCALLTYPE SetNameOf( + HWND hwnd, + LPCITEMIDLIST pidl, + LPCOLESTR lpszName, + SHGDNF uFlags, + LPITEMIDLIST *ppidlOut); + + // IShellFolder2 + virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID( + GUID *lpguid); + + virtual HRESULT STDMETHODCALLTYPE EnumSearches( + IEnumExtraSearch **ppenum); + + virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn( + DWORD dwReserved, + ULONG *pSort, + ULONG *pDisplay); + + virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState( + UINT iColumn, + SHCOLSTATEF *pcsFlags); + + virtual HRESULT STDMETHODCALLTYPE GetDetailsEx( + LPCITEMIDLIST pidl, + const SHCOLUMNID *pscid, + VARIANT *pv); + + virtual HRESULT STDMETHODCALLTYPE GetDetailsOf( + LPCITEMIDLIST pidl, + UINT iColumn, + SHELLDETAILS *psd); + + virtual HRESULT STDMETHODCALLTYPE MapColumnToSCID( + UINT iColumn, + SHCOLUMNID *pscid); + +}; diff --git a/base/shell/rshell/CStartMenu.cpp b/base/shell/rshell/CStartMenu.cpp index da990fa1b48..8312b56d1f5 100644 --- a/base/shell/rshell/CStartMenu.cpp +++ b/base/shell/rshell/CStartMenu.cpp @@ -284,11 +284,17 @@ CStartMenu_Constructor(REFIID riid, void **ppv) IShellMenu* pShellMenu; IBandSite* pBandSite; IDeskBar* pDeskBar; - LPITEMIDLIST pidlStartMenu; HRESULT hr; IShellFolder *shellFolder; - IShellFolder *psfStartMenu; + + LPITEMIDLIST pidlStartMenuUser; + IShellFolder *psfStartMenuUser; + +#if MERGE_FOLDERS + LPITEMIDLIST pidlStartMenuAll; + IShellFolder *psfStartMenuAll; +#endif #if USE_SYSTEM_MENUBAND hr = CoCreateInstance(CLSID_MenuBand, @@ -349,14 +355,31 @@ CStartMenu_Constructor(REFIID riid, void **ppv) if (FAILED(hr)) return hr; + hr = SHGetDesktopFolder(&shellFolder); + /* FIXME: Use CLSID_MergedFolder class and IID_IAugmentedShellFolder2 interface here */ /* CLSID_MergedFolder 26fdc864-be88-46e7-9235-032d8ea5162e */ /* IID_IAugmentedShellFolder2 8db3b3f4-6cfe-11d1-8ae9-00c04fd918d0 */ - hr = SHGetFolderLocation(NULL, CSIDL_STARTMENU, 0, 0, &pidlStartMenu); - hr = SHGetDesktopFolder(&shellFolder); - hr = shellFolder->BindToObject(pidlStartMenu, NULL, IID_IShellFolder, (void**) &psfStartMenu); + hr = SHGetFolderLocation(NULL, CSIDL_STARTMENU, 0, 0, &pidlStartMenuUser); + hr = shellFolder->BindToObject(pidlStartMenuUser, NULL, IID_IShellFolder, (void**) &psfStartMenuUser); - hr = pShellMenu->SetShellFolder(psfStartMenu, NULL, NULL, 0); +#if MERGE_FOLDERS + hr = SHGetFolderLocation(NULL, CSIDL_COMMON_STARTMENU, 0, 0, &pidlStartMenuAll); + hr = shellFolder->BindToObject(pidlStartMenuAll, NULL, IID_IShellFolder, (void**) &psfStartMenuAll); + + IShellFolder * psfMerged; + hr = CMergedFolder_Constructor(psfStartMenuUser, psfStartMenuAll, IID_PPV_ARG(IShellFolder, &psfMerged)); + if (FAILED(hr)) + return hr; + + hr = pShellMenu->SetShellFolder(psfMerged, NULL, NULL, 0); + if (FAILED(hr)) + return hr; +#else + hr = pShellMenu->SetShellFolder(psfStartMenuUser, NULL, NULL, 0); + if (FAILED(hr)) + return hr; +#endif hr = pDeskBar->SetClient(pBandSite); if (FAILED(hr)) diff --git a/base/shell/rshell/precomp.h b/base/shell/rshell/precomp.h index 4b1652f5800..bc08527cbfa 100644 --- a/base/shell/rshell/precomp.h +++ b/base/shell/rshell/precomp.h @@ -44,6 +44,7 @@ extern "C" HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv); extern "C" HRESULT CMenuDeskBar_Wrapper(IDeskBar * db, REFIID riid, LPVOID *ppv); extern "C" HRESULT CMenuSite_Wrapper(IBandSite * bs, REFIID riid, LPVOID *ppv); extern "C" HRESULT CMenuBand_Wrapper(IShellMenu * sm, REFIID riid, LPVOID *ppv); +extern "C" HRESULT CMergedFolder_Constructor(IShellFolder* userLocal, IShellFolder* allUsers, REFIID riid, LPVOID *ppv); static __inline ULONG Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...) diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt index f84298872e7..e1b8def8dea 100644 --- a/dll/win32/shell32/CMakeLists.txt +++ b/dll/win32/shell32/CMakeLists.txt @@ -1,3 +1,4 @@ +PROJECT(SHELL) set_cpp(WITH_RUNTIME)