[SHELL32] Load shell icon size from registry (#7683)

Improve usability. Re-trial of #7679 with different approach.
JIRA issue: CORE-12905
- Add ShellSmallIconSize, ShellLargeIconSize, and
  ShellIconBPP global variables in iconcache.cpp.
- Add SIC_GetMetricsValue, SIC_GetLargeIconSize,
  SIC_GetSmallIconSize, and SIC_GetIconBPP helper
  functions in iconcache.cpp.
- Load shell icon size from registry key
  "HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics".
- Load icon BPP (bits per pixel) from registry.
- Fix SIC_Initialize and SIC_LoadIcon functions for icon size.
- Fix SHGetFileInfoW function for SHGFI_SHELLICONSIZE flag.
This commit is contained in:
Katayama Hirofumi MZ 2025-01-31 08:21:05 +09:00 committed by GitHub
parent 909468c4dc
commit dddceeb10d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 93 additions and 71 deletions

View file

@ -1,21 +1,9 @@
/* /*
* shell icon cache (SIC) * PROJECT: ReactOS shell32
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 1998, 1999 Juergen Schmied * PURPOSE: Shell Icon Cache (SIC)
* * COPYRIGHT: Copyright 1998, 1999 Juergen Schmied
* This library is free software; you can redistribute it and/or * Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
* 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 "precomp.h"
@ -39,6 +27,9 @@ static HDPA sic_hdpa = 0;
static HIMAGELIST ShellSmallIconList; static HIMAGELIST ShellSmallIconList;
static HIMAGELIST ShellBigIconList; static HIMAGELIST ShellBigIconList;
INT ShellSmallIconSize = 0;
INT ShellLargeIconSize = 0;
INT ShellIconBPP = 0; // Bits Per Pixel
namespace namespace
{ {
@ -52,6 +43,48 @@ CRITICAL_SECTION_DEBUG critsect_debug =
CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 }; CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 };
} }
// Load metric value from registry
static INT
SIC_GetMetricsValue(
_In_ PCWSTR pszValueName,
_In_ INT nDefaultValue)
{
WCHAR szValue[64];
DWORD cbValue = sizeof(szValue);
DWORD error = SHGetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop\\WindowMetrics",
pszValueName, NULL, szValue, &cbValue);
if (error)
return nDefaultValue;
szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
return _wtoi(szValue);
}
static INT
SIC_GetLargeIconSize(VOID)
{
// NOTE: Shell icon size is always square
INT nDefaultSize = GetSystemMetrics(SM_CXICON);
INT nIconSize = SIC_GetMetricsValue(L"Shell Icon Size", nDefaultSize);
return (nIconSize > 0) ? nIconSize : nDefaultSize;
}
static INT
SIC_GetSmallIconSize(VOID)
{
// NOTE: Shell icon size is always square
INT nDefaultSize = GetSystemMetrics(SM_CXSMICON);
INT nIconSize = SIC_GetMetricsValue(L"Shell Small Icon Size", nDefaultSize);
return (nIconSize > 0) ? nIconSize : nDefaultSize;
}
static INT
SIC_GetIconBPP(VOID) // Bits Per Pixel
{
INT nDefaultBPP = SHGetCurColorRes();
INT nIconBPP = SIC_GetMetricsValue(L"Shell Icon BPP", nDefaultBPP);
return (nIconBPP > 0) ? nIconBPP : nDefaultBPP;
}
/***************************************************************************** /*****************************************************************************
* SIC_CompareEntries * SIC_CompareEntries
* *
@ -386,14 +419,15 @@ leave:
*/ */
static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags) static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
{ {
HICON hiconLarge=0; HICON hiconLarge = NULL, hiconSmall = NULL;
HICON hiconSmall=0;
UINT ret; UINT ret;
PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, LR_COPYFROMRESOURCE); PrivateExtractIconsW(sSourceFile, dwSourceIndex, ShellLargeIconSize, ShellLargeIconSize,
PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, LR_COPYFROMRESOURCE); &hiconLarge, NULL, 1, LR_COPYFROMRESOURCE);
PrivateExtractIconsW(sSourceFile, dwSourceIndex, ShellSmallIconSize, ShellSmallIconSize,
&hiconSmall, NULL, 1, LR_COPYFROMRESOURCE);
if ( !hiconLarge || !hiconSmall) if (!hiconLarge || !hiconSmall)
{ {
WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall); WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
if(hiconLarge) DestroyIcon(hiconLarge); if(hiconLarge) DestroyIcon(hiconLarge);
@ -481,9 +515,6 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags )
BOOL SIC_Initialize(void) BOOL SIC_Initialize(void)
{ {
HICON hSm = NULL, hLg = NULL; HICON hSm = NULL, hLg = NULL;
INT cx_small, cy_small;
INT cx_large, cy_large;
HDC hDC;
INT bpp; INT bpp;
DWORD ilMask; DWORD ilMask;
BOOL result = FALSE; BOOL result = FALSE;
@ -502,16 +533,10 @@ BOOL SIC_Initialize(void)
return FALSE; return FALSE;
} }
hDC = CreateICW(L"DISPLAY", NULL, NULL, NULL); ShellSmallIconSize = SIC_GetSmallIconSize();
if (!hDC) ShellLargeIconSize = SIC_GetLargeIconSize();
{
ERR("Failed to create information context (error %d)\n", GetLastError());
goto end;
}
bpp = GetDeviceCaps(hDC, BITSPIXEL);
DeleteDC(hDC);
bpp = ShellIconBPP = SIC_GetIconBPP(); // Bits Per Pixel
if (bpp <= 4) if (bpp <= 4)
ilMask = ILC_COLOR4; ilMask = ILC_COLOR4;
else if (bpp <= 8) else if (bpp <= 8)
@ -527,27 +552,14 @@ BOOL SIC_Initialize(void)
ilMask |= ILC_MASK; ilMask |= ILC_MASK;
cx_small = GetSystemMetrics(SM_CXSMICON); ShellSmallIconList = ImageList_Create(ShellSmallIconSize, ShellSmallIconSize, ilMask, 100, 100);
cy_small = GetSystemMetrics(SM_CYSMICON);
cx_large = GetSystemMetrics(SM_CXICON);
cy_large = GetSystemMetrics(SM_CYICON);
ShellSmallIconList = ImageList_Create(cx_small,
cy_small,
ilMask,
100,
100);
if (!ShellSmallIconList) if (!ShellSmallIconList)
{ {
ERR("Failed to create the small icon list.\n"); ERR("Failed to create the small icon list.\n");
goto end; goto end;
} }
ShellBigIconList = ImageList_Create(cx_large, ShellBigIconList = ImageList_Create(ShellLargeIconSize, ShellLargeIconSize, ilMask, 100, 100);
cy_large,
ilMask,
100,
100);
if (!ShellBigIconList) if (!ShellBigIconList)
{ {
ERR("Failed to create the big icon list.\n"); ERR("Failed to create the big icon list.\n");
@ -555,11 +567,8 @@ BOOL SIC_Initialize(void)
} }
/* Load the document icon, which is used as the default if an icon isn't found. */ /* Load the document icon, which is used as the default if an icon isn't found. */
hSm = (HICON)LoadImageW(shell32_hInstance, hSm = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), IMAGE_ICON, ShellSmallIconSize, ShellSmallIconSize,
IMAGE_ICON,
cx_small,
cy_small,
LR_SHARED | LR_DEFAULTCOLOR); LR_SHARED | LR_DEFAULTCOLOR);
if (!hSm) if (!hSm)
{ {
@ -567,11 +576,8 @@ BOOL SIC_Initialize(void)
goto end; goto end;
} }
hLg = (HICON)LoadImageW(shell32_hInstance, hLg = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), IMAGE_ICON, ShellLargeIconSize, ShellLargeIconSize,
IMAGE_ICON,
cx_large,
cy_large,
LR_SHARED | LR_DEFAULTCOLOR); LR_SHARED | LR_DEFAULTCOLOR);
if (!hLg) if (!hLg)
{ {

View file

@ -607,9 +607,6 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
if (flags & SHGFI_SELECTED) if (flags & SHGFI_SELECTED)
FIXME("set icon to selected, stub\n"); FIXME("set icon to selected, stub\n");
if (flags & SHGFI_SHELLICONSIZE)
FIXME("set icon to shell size, stub\n");
/* get the iconlocation */ /* get the iconlocation */
if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
{ {
@ -700,16 +697,32 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
else else
{ {
UINT ret; UINT ret;
if (flags & SHGFI_SMALLICON) INT cxIcon, cyIcon;
ret = PrivateExtractIconsW( sTemp,icon_idx,
GetSystemMetrics( SM_CXSMICON ), /* Get icon size */
GetSystemMetrics( SM_CYSMICON ), if (flags & SHGFI_SHELLICONSIZE)
&psfi->hIcon, 0, 1, 0); {
if (flags & SHGFI_SMALLICON)
cxIcon = cyIcon = ShellSmallIconSize;
else
cxIcon = cyIcon = ShellLargeIconSize;
}
else else
ret = PrivateExtractIconsW( sTemp, icon_idx, {
GetSystemMetrics( SM_CXICON), if (flags & SHGFI_SMALLICON)
GetSystemMetrics( SM_CYICON), {
&psfi->hIcon, 0, 1, 0); cxIcon = GetSystemMetrics(SM_CXSMICON);
cyIcon = GetSystemMetrics(SM_CYSMICON);
}
else
{
cxIcon = GetSystemMetrics(SM_CXICON);
cyIcon = GetSystemMetrics(SM_CYICON);
}
}
ret = PrivateExtractIconsW(sTemp, icon_idx, cxIcon, cyIcon,
&psfi->hIcon, 0, 1, 0);
if (ret != 0 && ret != (UINT)-1) if (ret != 0 && ret != (UINT)-1)
{ {
IconNotYetLoaded=FALSE; IconNotYetLoaded=FALSE;

View file

@ -44,6 +44,9 @@ BOOL SIC_Initialize(void);
void SIC_Destroy(void) DECLSPEC_HIDDEN; void SIC_Destroy(void) DECLSPEC_HIDDEN;
BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex) DECLSPEC_HIDDEN; BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex) DECLSPEC_HIDDEN;
INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DECLSPEC_HIDDEN; INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DECLSPEC_HIDDEN;
extern INT ShellLargeIconSize;
extern INT ShellSmallIconSize;
extern INT ShellIconBPP;
/* Classes Root */ /* Classes Root */
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback); HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback);