[SHELL32] Allow custom shortcut overlay icon (#6419)

Use correct icon index in SIC_OverlayShortcutImage() to properly load
shortcut overlay icon from registry instead of always using default icon.
This allows to use custom shortcut icon set by user, in case it was
specified there.

As FIXME comment stated, the icon indexes were not implemented in the far
past, so this workaround was badly required. But now they are implemented,
so no need to always use default resource from shell32, enable the correct
code instead.

Also adapt this to CShellLink::CreateShortcutIcon() when the shortcut icon
is being changed in its properties dialog, as well as in CNewMenu class
when displaying menu items for creating a new folder or a shortcut.

Addendum to f9a5344254. CORE-14758
This commit is contained in:
Oleg Dubinskiy 2024-03-04 14:30:43 +01:00 committed by GitHub
parent bbbcd8ed68
commit eb96d377d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 47 additions and 10 deletions

View file

@ -33,6 +33,8 @@ CNewMenu::CNewMenu() :
m_idCmdFirst(0), m_idCmdFirst(0),
m_idCmdFolder(-1), m_idCmdFolder(-1),
m_idCmdLink(-1), m_idCmdLink(-1),
m_bCustomIconFolder(FALSE),
m_bCustomIconLink(FALSE),
m_hIconFolder(NULL), m_hIconFolder(NULL),
m_hIconLink(NULL) m_hIconLink(NULL)
{ {
@ -42,6 +44,10 @@ CNewMenu::~CNewMenu()
{ {
UnloadAllItems(); UnloadAllItems();
if (m_bCustomIconFolder && m_hIconFolder)
DestroyIcon(m_hIconFolder);
if (m_bCustomIconLink && m_hIconLink)
DestroyIcon(m_hIconLink);
if (m_pidlFolder) if (m_pidlFolder)
ILFree(m_pidlFolder); ILFree(m_pidlFolder);
} }
@ -768,10 +774,32 @@ HRESULT WINAPI
CNewMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, CNewMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder,
IDataObject *pdtobj, HKEY hkeyProgID) IDataObject *pdtobj, HKEY hkeyProgID)
{ {
const INT cx = GetSystemMetrics(SM_CXSMICON), cy = GetSystemMetrics(SM_CYSMICON);
WCHAR wszIconPath[MAX_PATH];
int icon_idx;
m_pidlFolder = ILClone(pidlFolder); m_pidlFolder = ILClone(pidlFolder);
/* Load folder and shortcut icons */ /* Load folder and shortcut icons */
m_hIconFolder = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 16, 16, LR_SHARED); if (HLM_GetIconW(IDI_SHELL_FOLDER - 1, wszIconPath, _countof(wszIconPath), &icon_idx))
m_hIconLink = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 16, 16, LR_SHARED); {
::ExtractIconExW(wszIconPath, icon_idx, &m_hIconFolder, NULL, 1);
m_bCustomIconFolder = TRUE;
}
else
{
m_hIconFolder = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, cx, cy, LR_SHARED);
}
if (HLM_GetIconW(IDI_SHELL_SHORTCUT - 1, wszIconPath, _countof(wszIconPath), &icon_idx))
{
::ExtractIconExW(wszIconPath, icon_idx, &m_hIconLink, NULL, 1);
m_bCustomIconLink = TRUE;
}
else
{
m_hIconLink = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, cx, cy, LR_SHARED);
}
return S_OK; return S_OK;
} }

View file

@ -59,6 +59,7 @@ private:
CComPtr<IUnknown> m_pSite; CComPtr<IUnknown> m_pSite;
HMENU m_hSubMenu; HMENU m_hSubMenu;
UINT m_idCmdFirst, m_idCmdFolder, m_idCmdLink; UINT m_idCmdFirst, m_idCmdFolder, m_idCmdLink;
BOOL m_bCustomIconFolder, m_bCustomIconLink;
HICON m_hIconFolder, m_hIconLink; HICON m_hIconFolder, m_hIconLink;
SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt); SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt);

View file

@ -3155,11 +3155,21 @@ HICON CShellLink::CreateShortcutIcon(LPCWSTR wszIconPath, INT IconIndex)
{ {
const INT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON); const INT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);
const COLORREF crMask = GetSysColor(COLOR_3DFACE); const COLORREF crMask = GetSysColor(COLOR_3DFACE);
WCHAR wszLnkIcon[MAX_PATH];
int lnk_idx;
HDC hDC; HDC hDC;
HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, 1, 1); HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, 1, 1);
HICON hIcon = NULL, hNewIcon = NULL; HICON hIcon = NULL, hNewIcon = NULL, hShortcut;
HICON hShortcut = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT),
IMAGE_ICON, cx, cy, 0); if (HLM_GetIconW(IDI_SHELL_SHORTCUT - 1, wszLnkIcon, _countof(wszLnkIcon), &lnk_idx))
{
::ExtractIconExW(wszLnkIcon, lnk_idx, &hShortcut, NULL, 1);
}
else
{
hShortcut = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT),
IMAGE_ICON, cx, cy, 0);
}
::ExtractIconExW(wszIconPath, IconIndex, &hIcon, NULL, 1); ::ExtractIconExW(wszIconPath, IconIndex, &hIcon, NULL, 1);
if (!hIcon || !hShortcut || !himl) if (!hIcon || !hShortcut || !himl)

View file

@ -1085,6 +1085,7 @@ void CFileDefExt::UpdateFolderIcon(HWND hwndDlg)
// create the icon // create the icon
if (m_szFolderIconPath[0] == 0 && m_nFolderIconIndex == 0) if (m_szFolderIconPath[0] == 0 && m_nFolderIconIndex == 0)
{ {
// Windows ignores shell customization here and uses the default icon
m_hFolderIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER)); m_hFolderIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER));
} }
else else

View file

@ -122,10 +122,7 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
/* search for the shortcut icon only once */ /* search for the shortcut icon only once */
if (s_imgListIdx == -1) if (s_imgListIdx == -1)
s_imgListIdx = SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT); s_imgListIdx = SIC_LoadOverlayIcon(IDI_SHELL_SHORTCUT - 1);
/* FIXME should use icon index 29 instead of the
resource id, but not all icons are present yet
so we can't use icon indices */
if (s_imgListIdx != -1) if (s_imgListIdx != -1)
{ {

View file

@ -352,7 +352,7 @@ BOOL HCU_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int
{ {
ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx); ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx);
RegCloseKey(hkey); RegCloseKey(hkey);
} }
if (ret) if (ret)
TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx); TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);