[SHELL32] DefView statusbar item file size fix in recycler and UNC (#7732)

- Display item sizes inside \\ UNC paths.
- Don't display anything in the location pane inside the Recycle Bin (CORE-20005).
- Don't display the size and location panes in My Computer
- Don't update the location pane on simple item selection changes.

CORE-20005
This commit is contained in:
Whindmar Saksit 2025-03-27 18:29:44 +01:00 committed by GitHub
parent c7eba0c5c7
commit b6562a664b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 95 additions and 73 deletions

View file

@ -273,7 +273,8 @@ private:
CComPtr<IContextMenu> m_pFileMenu;
BOOL m_isEditing;
BOOL m_isParentFolderSpecial;
signed char m_SpecialFolder;
bool m_isFullStatusBar;
bool m_ScheduledStatusbarUpdate;
bool m_HasCutItems;
@ -294,6 +295,12 @@ private:
void _DoCopyToMoveToFolder(BOOL bCopy);
BOOL IsDesktop() const { return m_FolderSettings.fFlags & FWF_DESKTOP; }
inline BOOL IsSpecialFolder(int &csidl) const
{
csidl = m_SpecialFolder;
return m_SpecialFolder >= 0;
}
public:
CDefView();
~CDefView();
@ -302,6 +309,7 @@ public:
HRESULT OnDefaultCommand();
HRESULT OnStateChange(UINT uFlags);
void UpdateStatusbar();
void UpdateStatusbarLocation();
void CheckToolbar();
BOOL CreateList();
void UpdateListColors();
@ -601,7 +609,8 @@ CDefView::CDefView() :
m_iDragOverItem(0),
m_cScrollDelay(0),
m_isEditing(FALSE),
m_isParentFolderSpecial(FALSE),
m_SpecialFolder(-1),
m_isFullStatusBar(true),
m_ScheduledStatusbarUpdate(false),
m_HasCutItems(false),
m_Destroyed(FALSE)
@ -721,8 +730,8 @@ void CDefView::CheckToolbar()
void CDefView::UpdateStatusbar()
{
WCHAR szFormat[MAX_PATH] = {0};
WCHAR szPartText[MAX_PATH] = {0};
WCHAR szFormat[MAX_PATH];
WCHAR szPartText[MAX_PATH];
UINT cSelectedItems;
if (!m_ListView)
@ -744,11 +753,10 @@ void CDefView::UpdateStatusbar()
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szPartText, &lResult);
// Don't bother with the extra processing if we only have one StatusBar part
if (!m_isParentFolderSpecial)
if (m_isFullStatusBar)
{
UINT64 uTotalFileSize = 0;
WORD uFileFlags = LVNI_ALL;
LPARAM pIcon = NULL;
INT nItem = -1;
bool bIsOnlyFoldersSelected = true;
@ -773,25 +781,11 @@ void CDefView::UpdateStatusbar()
// Don't show the file size text if there is 0 bytes in the folder
// OR we only have folders selected
if ((cSelectedItems && !bIsOnlyFoldersSelected) || uTotalFileSize)
{
StrFormatByteSizeW(uTotalFileSize, szPartText, _countof(szPartText));
}
else
{
*szPartText = 0;
}
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 1, (LPARAM)szPartText, &lResult);
// If we are in a Recycle Bin then show no text for the location part
if (!_ILIsBitBucket(m_pidlParent))
{
LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText, _countof(szPartText));
pIcon = (LPARAM)m_hMyComputerIcon;
}
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETICON, 2, pIcon, &lResult);
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 2, (LPARAM)szPartText, &lResult);
}
SFGAOF att = 0;
@ -806,6 +800,32 @@ void CDefView::UpdateStatusbar()
m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, FCIDM_SHVIEW_MOVETO, (att & SFGAO_CANMOVE) != 0, &lResult);
}
void CDefView::UpdateStatusbarLocation()
{
LRESULT lResult;
LPARAM pIcon = NULL;
WCHAR szPartText[MAX_PATH];
*szPartText = 0;
if (m_isFullStatusBar)
{
// If we are in a Recycle Bin then show no text for the location part
int csidl;
if (!IsSpecialFolder(csidl) || (csidl != CSIDL_NETWORK && csidl != CSIDL_BITBUCKET))
{
LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText, _countof(szPartText));
pIcon = (LPARAM)m_hMyComputerIcon;
}
/*else if (csidl == CSIDL_NETWORK) // TODO: Figure out the type of share (My Computer/Local Intranet/Internet?)
{
ImageList_GetIconSize(ListView_GetImageList(m_ListView, LVSIL_SMALL), &x, &y);
pIcon = (LPARAM)LoadImage(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_MY_NETWORK_PLACES),
IMAGE_ICON, x, y, LR_SHARED);
}*/
}
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETICON, 2, pIcon, &lResult);
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 2, (LPARAM)szPartText, &lResult);
}
LRESULT CDefView::OnUpdateStatusbar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
m_ScheduledStatusbarUpdate = false;
@ -1555,7 +1575,7 @@ HRESULT CDefView::FillList(BOOL IsRefreshCommand)
// copy the items into the array
while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
{
if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
if (DPA_AppendPtr(hdpa, pidl) == -1)
{
SHFree(pidl);
}
@ -1605,6 +1625,9 @@ HRESULT CDefView::FillList(BOOL IsRefreshCommand)
m_ListView.InvalidateRect(NULL, TRUE);
}
if (IsRefreshCommand)
UpdateStatusbarLocation();
_DoFolderViewCB(SFVM_LISTREFRESHED, 0, 0);
return S_OK;
@ -1793,22 +1816,27 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
BOOL bPreviousParentSpecial = m_isParentFolderSpecial;
// A folder is special if it is the Desktop folder,
// a network folder, or a Control Panel folder
m_isParentFolderSpecial = IsDesktop() || _ILIsNetHood(m_pidlParent)
|| _ILIsControlPanel(ILFindLastID(m_pidlParent));
// Only force StatusBar part refresh if the state
// changed from the previous folder
if (bPreviousParentSpecial != m_isParentFolderSpecial)
int bForceFullStatusBar = false;
BOOL bIsFileSystem = SHGetAttributes(NULL, m_pidlParent, SFGAO_FILESYSTEM) & SFGAO_FILESYSTEM;
m_SpecialFolder = bIsFileSystem ? -1 : 0x7f; // FS folder or "generic" CSIDL
if (_ILIsDesktop(m_pidlParent))
{
// This handles changing StatusBar parts
_ForceStatusBarResize();
m_SpecialFolder = CSIDL_DESKTOP;
}
else if (IsEqualPersistClassID(ppf2, CLSID_RecycleBin))
{
m_SpecialFolder = bForceFullStatusBar = CSIDL_BITBUCKET;
}
else if (bIsFileSystem)
{
CComHeapPtr<ITEMIDLIST> pidlNet(SHCloneSpecialIDList(NULL, CSIDL_NETWORK, FALSE));
if (ILIsParent(pidlNet, m_pidlParent, FALSE) && ILGetSize(pidlNet) < ILGetSize(m_pidlParent))
m_SpecialFolder = CSIDL_NETWORK;
}
m_isFullStatusBar = bIsFileSystem || bForceFullStatusBar;
_ForceStatusBarResize(); // This handles changing StatusBar parts
UpdateStatusbar();
UpdateStatusbarLocation();
return S_OK;
}
@ -4474,7 +4502,7 @@ void CDefView::_HandleStatusBarResize(int nWidth)
{
LRESULT lResult;
if (m_isParentFolderSpecial)
if (!m_isFullStatusBar)
{
int nPartArray[] = {-1};
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, _countof(nPartArray), (LPARAM)nPartArray, &lResult);

View file

@ -54,6 +54,12 @@ static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
return NULL;
}
static bool IsRegItem(PCUITEMID_CHILD pidl, REFCLSID clsid)
{
const CLSID *pClass = IsRegItem(pidl);
return pClass && *pClass == clsid;
}
static inline void MarkAsCommonItem(LPITEMIDLIST pidl)
{
ASSERT(_ILGetFSType(pidl) & PT_FS);
@ -708,12 +714,12 @@ HRESULT WINAPI CDesktopFolder::GetAttributesOf(
/* TODO: always add SFGAO_CANLINK */
for (UINT i = 0; i < cidl; ++i)
{
pdump(*apidl);
if (_ILIsDesktop(*apidl))
pdump(apidl[i]);
if (_ILIsDesktop(apidl[i]))
*rgfInOut &= dwDesktopAttributes;
else if (_ILIsMyComputer(apidl[i]))
*rgfInOut &= dwMyComputerAttributes;
else if (_ILIsNetHood(apidl[i]))
else if (IsRegItem(apidl[i], CLSID_NetworkPlaces))
*rgfInOut &= dwMyNetPlacesAttributes;
else if (_ILIsFolderOrFile(apidl[i]) || _ILIsSpecialFolder(apidl[i]))
{

View file

@ -78,6 +78,12 @@ static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
return NULL;
}
static bool IsRegItem(PCUITEMID_CHILD pidl, REFCLSID clsid)
{
const CLSID *pClass = IsRegItem(pidl);
return pClass && *pClass == clsid;
}
static INT8 GetDriveNumber(PCUITEMID_CHILD pidl)
{
if (!_ILIsDrive(pidl))
@ -99,6 +105,7 @@ template<class T> static T* GetDrivePath(PCUITEMID_CHILD pidl, T *Path)
return Path;
}
BOOL _ILGetDriveType(LPCITEMIDLIST pidl)
{
WCHAR szDrive[8];
@ -586,7 +593,7 @@ static const shvheader MyComputerSFHeader[] = {
static const DWORD dwComputerAttributes =
SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
static const DWORD dwControlPanelAttributes =
SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
static const DWORD dwDriveAttributes =
@ -875,7 +882,6 @@ HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY a
if (*rgfInOut == 0)
*rgfInOut = ~0;
/* FIXME: always add SFGAO_CANLINK */
if(cidl == 0)
*rgfInOut &= dwComputerAttributes;
else
@ -889,7 +895,7 @@ HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY a
if (_ILGetDriveType(apidl[i]) == DRIVE_CDROM)
*rgfInOut &= ~SFGAO_CANRENAME; // CD-ROM drive cannot rename
}
else if (_ILIsControlPanel(apidl[i]))
else if (IsRegItem(apidl[i], CLSID_ControlPanel))
{
*rgfInOut &= dwControlPanelAttributes;
}

View file

@ -24,6 +24,13 @@ SHELL_ErrorBox(CMINVOKECOMMANDINFO &cmi, UINT Error)
}
#endif
static inline BOOL
IsEqualPersistClassID(IPersist *pPersist, REFCLSID clsid)
{
CLSID temp;
return pPersist && SUCCEEDED(pPersist->GetClassID(&temp)) && IsEqualCLSID(clsid, temp);
}
static inline BOOL
RegValueExists(HKEY hKey, LPCWSTR Name)
{

View file

@ -1763,30 +1763,29 @@ LPITEMIDLIST _ILCreateDesktop(void)
LPITEMIDLIST _ILCreateMyComputer(void)
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_MyComputer);
return _ILCreateGuid(PT_DESKTOP_REGITEM, &CLSID_MyComputer);
}
LPITEMIDLIST _ILCreateMyDocuments(void)
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_MyDocuments);
return _ILCreateGuid(PT_DESKTOP_REGITEM, &CLSID_MyDocuments);
}
LPITEMIDLIST _ILCreateIExplore(void)
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_Internet);
return _ILCreateGuid(PT_DESKTOP_REGITEM, &CLSID_Internet);
}
LPITEMIDLIST _ILCreateControlPanel(void)
{
LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL;
LPITEMIDLIST parent = _ILCreateMyComputer(), ret = NULL;
TRACE("()\n");
if (parent)
{
LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel);
LPITEMIDLIST cpl = _ILCreateGuid(PT_COMPUTER_REGITEM, &CLSID_ControlPanel);
if (cpl)
{
ret = ILCombine(parent, cpl);
@ -1827,13 +1826,13 @@ LPITEMIDLIST _ILCreatePrinters(void)
LPITEMIDLIST _ILCreateNetwork(void)
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_NetworkPlaces);
return _ILCreateGuid(PT_DESKTOP_REGITEM, &CLSID_NetworkPlaces);
}
LPITEMIDLIST _ILCreateBitBucket(void)
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_RecycleBin);
return _ILCreateGuid(PT_DESKTOP_REGITEM, &CLSID_RecycleBin);
}
LPITEMIDLIST _ILCreateAdminTools(void)
@ -2060,28 +2059,6 @@ BOOL _ILIsMyDocuments(LPCITEMIDLIST pidl)
return FALSE;
}
BOOL _ILIsNetHood(LPCITEMIDLIST pidl)
{
IID *iid = _ILGetGUIDPointer(pidl);
TRACE("(%p)\n", pidl);
if (iid)
return IsEqualIID(iid, &CLSID_NetworkPlaces);
return FALSE;
}
BOOL _ILIsControlPanel(LPCITEMIDLIST pidl)
{
IID *iid = _ILGetGUIDPointer(pidl);
TRACE("(%p)\n", pidl);
if (iid)
return IsEqualIID(iid, &CLSID_ControlPanel);
return FALSE;
}
BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
{
REFIID iid = _ILGetGUIDPointer(pidl);

View file

@ -248,8 +248,6 @@ BOOL _ILIsMyComputer (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
#ifdef __REACTOS__
BOOL _ILIsMyDocuments (LPCITEMIDLIST pidl);
BOOL _ILIsBitBucket (LPCITEMIDLIST pidl);
BOOL _ILIsNetHood (LPCITEMIDLIST pidl);
BOOL _ILIsControlPanel (LPCITEMIDLIST pidl);
#define _ILIsFolderOrFile _ILGetFSType
#endif
BOOL _ILIsDrive (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;