Reactos

[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.

authored by

Katayama Hirofumi MZ and committed by
GitHub
dddceeb1 909468c4

+93 -71
+65 -59
dll/win32/shell32/iconcache.cpp
··· 1 1 /* 2 - * shell icon cache (SIC) 3 - * 4 - * Copyright 1998, 1999 Juergen Schmied 5 - * 6 - * This library is free software; you can redistribute it and/or 7 - * modify it under the terms of the GNU Lesser General Public 8 - * License as published by the Free Software Foundation; either 9 - * version 2.1 of the License, or (at your option) any later version. 10 - * 11 - * This library is distributed in the hope that it will be useful, 12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 - * Lesser General Public License for more details. 15 - * 16 - * You should have received a copy of the GNU Lesser General Public 17 - * License along with this library; if not, write to the Free Software 18 - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 2 + * PROJECT: ReactOS shell32 3 + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 + * PURPOSE: Shell Icon Cache (SIC) 5 + * COPYRIGHT: Copyright 1998, 1999 Juergen Schmied 6 + * Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 19 7 */ 20 8 21 9 #include "precomp.h" ··· 39 27 40 28 static HIMAGELIST ShellSmallIconList; 41 29 static HIMAGELIST ShellBigIconList; 30 + INT ShellSmallIconSize = 0; 31 + INT ShellLargeIconSize = 0; 32 + INT ShellIconBPP = 0; // Bits Per Pixel 42 33 43 34 namespace 44 35 { ··· 50 41 0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_SicCS") } 51 42 }; 52 43 CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 }; 44 + } 45 + 46 + // Load metric value from registry 47 + static INT 48 + SIC_GetMetricsValue( 49 + _In_ PCWSTR pszValueName, 50 + _In_ INT nDefaultValue) 51 + { 52 + WCHAR szValue[64]; 53 + DWORD cbValue = sizeof(szValue); 54 + DWORD error = SHGetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop\\WindowMetrics", 55 + pszValueName, NULL, szValue, &cbValue); 56 + if (error) 57 + return nDefaultValue; 58 + szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun 59 + return _wtoi(szValue); 60 + } 61 + 62 + static INT 63 + SIC_GetLargeIconSize(VOID) 64 + { 65 + // NOTE: Shell icon size is always square 66 + INT nDefaultSize = GetSystemMetrics(SM_CXICON); 67 + INT nIconSize = SIC_GetMetricsValue(L"Shell Icon Size", nDefaultSize); 68 + return (nIconSize > 0) ? nIconSize : nDefaultSize; 69 + } 70 + 71 + static INT 72 + SIC_GetSmallIconSize(VOID) 73 + { 74 + // NOTE: Shell icon size is always square 75 + INT nDefaultSize = GetSystemMetrics(SM_CXSMICON); 76 + INT nIconSize = SIC_GetMetricsValue(L"Shell Small Icon Size", nDefaultSize); 77 + return (nIconSize > 0) ? nIconSize : nDefaultSize; 78 + } 79 + 80 + static INT 81 + SIC_GetIconBPP(VOID) // Bits Per Pixel 82 + { 83 + INT nDefaultBPP = SHGetCurColorRes(); 84 + INT nIconBPP = SIC_GetMetricsValue(L"Shell Icon BPP", nDefaultBPP); 85 + return (nIconBPP > 0) ? nIconBPP : nDefaultBPP; 53 86 } 54 87 55 88 /***************************************************************************** ··· 386 419 */ 387 420 static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags) 388 421 { 389 - HICON hiconLarge=0; 390 - HICON hiconSmall=0; 422 + HICON hiconLarge = NULL, hiconSmall = NULL; 391 423 UINT ret; 392 424 393 - PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, LR_COPYFROMRESOURCE); 394 - PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, LR_COPYFROMRESOURCE); 425 + PrivateExtractIconsW(sSourceFile, dwSourceIndex, ShellLargeIconSize, ShellLargeIconSize, 426 + &hiconLarge, NULL, 1, LR_COPYFROMRESOURCE); 427 + PrivateExtractIconsW(sSourceFile, dwSourceIndex, ShellSmallIconSize, ShellSmallIconSize, 428 + &hiconSmall, NULL, 1, LR_COPYFROMRESOURCE); 395 429 396 - if ( !hiconLarge || !hiconSmall) 430 + if (!hiconLarge || !hiconSmall) 397 431 { 398 432 WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall); 399 433 if(hiconLarge) DestroyIcon(hiconLarge); ··· 481 515 BOOL SIC_Initialize(void) 482 516 { 483 517 HICON hSm = NULL, hLg = NULL; 484 - INT cx_small, cy_small; 485 - INT cx_large, cy_large; 486 - HDC hDC; 487 518 INT bpp; 488 519 DWORD ilMask; 489 520 BOOL result = FALSE; ··· 502 533 return FALSE; 503 534 } 504 535 505 - hDC = CreateICW(L"DISPLAY", NULL, NULL, NULL); 506 - if (!hDC) 507 - { 508 - ERR("Failed to create information context (error %d)\n", GetLastError()); 509 - goto end; 510 - } 511 - 512 - bpp = GetDeviceCaps(hDC, BITSPIXEL); 513 - DeleteDC(hDC); 536 + ShellSmallIconSize = SIC_GetSmallIconSize(); 537 + ShellLargeIconSize = SIC_GetLargeIconSize(); 514 538 539 + bpp = ShellIconBPP = SIC_GetIconBPP(); // Bits Per Pixel 515 540 if (bpp <= 4) 516 541 ilMask = ILC_COLOR4; 517 542 else if (bpp <= 8) ··· 527 552 528 553 ilMask |= ILC_MASK; 529 554 530 - cx_small = GetSystemMetrics(SM_CXSMICON); 531 - cy_small = GetSystemMetrics(SM_CYSMICON); 532 - cx_large = GetSystemMetrics(SM_CXICON); 533 - cy_large = GetSystemMetrics(SM_CYICON); 534 - 535 - ShellSmallIconList = ImageList_Create(cx_small, 536 - cy_small, 537 - ilMask, 538 - 100, 539 - 100); 555 + ShellSmallIconList = ImageList_Create(ShellSmallIconSize, ShellSmallIconSize, ilMask, 100, 100); 540 556 if (!ShellSmallIconList) 541 557 { 542 558 ERR("Failed to create the small icon list.\n"); 543 559 goto end; 544 560 } 545 561 546 - ShellBigIconList = ImageList_Create(cx_large, 547 - cy_large, 548 - ilMask, 549 - 100, 550 - 100); 562 + ShellBigIconList = ImageList_Create(ShellLargeIconSize, ShellLargeIconSize, ilMask, 100, 100); 551 563 if (!ShellBigIconList) 552 564 { 553 565 ERR("Failed to create the big icon list.\n"); ··· 555 567 } 556 568 557 569 /* Load the document icon, which is used as the default if an icon isn't found. */ 558 - hSm = (HICON)LoadImageW(shell32_hInstance, 559 - MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), 560 - IMAGE_ICON, 561 - cx_small, 562 - cy_small, 570 + hSm = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), 571 + IMAGE_ICON, ShellSmallIconSize, ShellSmallIconSize, 563 572 LR_SHARED | LR_DEFAULTCOLOR); 564 573 if (!hSm) 565 574 { ··· 567 576 goto end; 568 577 } 569 578 570 - hLg = (HICON)LoadImageW(shell32_hInstance, 571 - MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), 572 - IMAGE_ICON, 573 - cx_large, 574 - cy_large, 579 + hLg = (HICON)LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT), 580 + IMAGE_ICON, ShellLargeIconSize, ShellLargeIconSize, 575 581 LR_SHARED | LR_DEFAULTCOLOR); 576 582 if (!hLg) 577 583 {
+25 -12
dll/win32/shell32/wine/shell32_main.c
··· 607 607 if (flags & SHGFI_SELECTED) 608 608 FIXME("set icon to selected, stub\n"); 609 609 610 - if (flags & SHGFI_SHELLICONSIZE) 611 - FIXME("set icon to shell size, stub\n"); 612 - 613 610 /* get the iconlocation */ 614 611 if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) 615 612 { ··· 700 697 else 701 698 { 702 699 UINT ret; 703 - if (flags & SHGFI_SMALLICON) 704 - ret = PrivateExtractIconsW( sTemp,icon_idx, 705 - GetSystemMetrics( SM_CXSMICON ), 706 - GetSystemMetrics( SM_CYSMICON ), 707 - &psfi->hIcon, 0, 1, 0); 700 + INT cxIcon, cyIcon; 701 + 702 + /* Get icon size */ 703 + if (flags & SHGFI_SHELLICONSIZE) 704 + { 705 + if (flags & SHGFI_SMALLICON) 706 + cxIcon = cyIcon = ShellSmallIconSize; 707 + else 708 + cxIcon = cyIcon = ShellLargeIconSize; 709 + } 708 710 else 709 - ret = PrivateExtractIconsW( sTemp, icon_idx, 710 - GetSystemMetrics( SM_CXICON), 711 - GetSystemMetrics( SM_CYICON), 712 - &psfi->hIcon, 0, 1, 0); 711 + { 712 + if (flags & SHGFI_SMALLICON) 713 + { 714 + cxIcon = GetSystemMetrics(SM_CXSMICON); 715 + cyIcon = GetSystemMetrics(SM_CYSMICON); 716 + } 717 + else 718 + { 719 + cxIcon = GetSystemMetrics(SM_CXICON); 720 + cyIcon = GetSystemMetrics(SM_CYICON); 721 + } 722 + } 723 + 724 + ret = PrivateExtractIconsW(sTemp, icon_idx, cxIcon, cyIcon, 725 + &psfi->hIcon, 0, 1, 0); 713 726 if (ret != 0 && ret != (UINT)-1) 714 727 { 715 728 IconNotYetLoaded=FALSE;
+3
dll/win32/shell32/wine/shell32_main.h
··· 44 44 void SIC_Destroy(void) DECLSPEC_HIDDEN; 45 45 BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex) DECLSPEC_HIDDEN; 46 46 INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DECLSPEC_HIDDEN; 47 + extern INT ShellLargeIconSize; 48 + extern INT ShellSmallIconSize; 49 + extern INT ShellIconBPP; 47 50 48 51 /* Classes Root */ 49 52 HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback);