From 3a1b289d66db4fa4e1afe9777eafe7a618312808 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 2 May 2017 16:12:34 +0100 Subject: [PATCH] shell32: Fix the icon sizes of the shell imagelists. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/shell32/iconcache.c | 42 ++++++++++++++++++++++++++---- dlls/shell32/tests/shelllink.c | 58 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c index 737f4d50234..59fd8fb104a 100644 --- a/dlls/shell32/iconcache.c +++ b/dlls/shell32/iconcache.c @@ -73,6 +73,11 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static const WCHAR WindowMetrics[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p','\\', + 'W','i','n','d','o','w','M','e','t','r','i','c','s',0}; +static const WCHAR ShellIconSize[] = {'S','h','e','l','l',' ','I','c','o','n',' ','S','i','z','e',0}; + /***************************************************************************** * SIC_CompareEntries * @@ -361,6 +366,24 @@ static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags) return ret; } +static int get_shell_icon_size(void) +{ + WCHAR buf[32]; + DWORD value = 32, size = sizeof(buf), type; + HKEY key; + + if (!RegOpenKeyW( HKEY_CURRENT_USER, WindowMetrics, &key )) + { + if (!RegQueryValueExW( key, ShellIconSize, NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ) + { + if (size == sizeof(buf)) buf[size / sizeof(WCHAR) - 1] = 0; + value = atoiW( buf ); + } + RegCloseKey( key ); + } + return value; +} + /***************************************************************************** * SIC_Initialize [internal] */ @@ -370,12 +393,21 @@ static BOOL WINAPI SIC_Initialize( INIT_ONCE *once, void *param, void **context int cx_small, cy_small; int cx_large, cy_large; - cx_small = GetSystemMetrics(SM_CXSMICON); - cy_small = GetSystemMetrics(SM_CYSMICON); - cx_large = GetSystemMetrics(SM_CXICON); - cy_large = GetSystemMetrics(SM_CYICON); + if (!IsProcessDPIAware()) + { + cx_large = cy_large = get_shell_icon_size(); + cx_small = GetSystemMetrics( SM_CXSMICON ); + cy_small = GetSystemMetrics( SM_CYSMICON ); + } + else + { + cx_large = GetSystemMetrics( SM_CXICON ); + cy_large = GetSystemMetrics( SM_CYICON ); + cx_small = cx_large / 2; + cy_small = cy_large / 2; + } - TRACE("\n"); + TRACE("large %dx%d small %dx%d\n", cx_large, cy_large, cx_small, cx_small); sic_hdpa = DPA_Create(16); diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index db15ccd7ed8..ad254c83498 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -44,6 +44,7 @@ static HRESULT (WINAPI *pSHGetStockIconInfo)(SHSTOCKICONID, UINT, SHSTOCKICONINF static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR, LPSTR, DWORD); static DWORD (WINAPI *pGetShortPathNameA)(LPCSTR, LPSTR, DWORD); static UINT (WINAPI *pSHExtractIconsW)(LPCWSTR, int, int, int, HICON *, UINT *, UINT, UINT); +static BOOL (WINAPI *pIsProcessDPIAware)(void); static const GUID _IID_IShellLinkDataList = { 0x45e2b4ae, 0xb1c3, 0x11d0, @@ -1304,6 +1305,21 @@ todo_wine { DestroyIcon(hicon); } +static int get_shell_icon_size(void) +{ + char buf[10]; + DWORD value = 32, size = sizeof(buf), type; + HKEY key; + + if (!RegOpenKeyA( HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", &key )) + { + if (!RegQueryValueExA( key, "Shell Icon Size", NULL, &type, (BYTE *)buf, &size ) && type == REG_SZ) + value = atoi( buf ); + RegCloseKey( key ); + } + return value; +} + static void test_SHGetImageList(void) { HRESULT hr; @@ -1311,6 +1327,8 @@ static void test_SHGetImageList(void) BOOL ret; HIMAGELIST lg, sm; ULONG start_refs, refs; + int i, width, height, expect; + BOOL dpi_aware = pIsProcessDPIAware && pIsProcessDPIAware(); hr = SHGetImageList( SHIL_LARGE, &IID_IImageList, (void **)&list ); ok( hr == S_OK, "got %08x\n", hr ); @@ -1340,6 +1358,44 @@ static void test_SHGetImageList(void) IImageList_Release( list2 ); IImageList_Release( list ); + + /* Test the icon sizes */ + for (i = 0; i <= SHIL_LAST; i++) + { + hr = SHGetImageList( i, &IID_IImageList, (void **)&list ); + todo_wine_if(i == SHIL_EXTRALARGE || i == SHIL_JUMBO) + ok( hr == S_OK || + broken( i == SHIL_JUMBO && hr == E_INVALIDARG ), /* XP and 2003 */ + "%d: got %08x\n", i, hr ); + if (FAILED(hr)) continue; + IImageList_GetIconSize( list, &width, &height ); + switch (i) + { + case SHIL_LARGE: + if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ); + else expect = get_shell_icon_size(); + break; + case SHIL_SMALL: + if (dpi_aware) expect = GetSystemMetrics( SM_CXICON ) / 2; + else expect = GetSystemMetrics( SM_CXSMICON ); + break; + case SHIL_EXTRALARGE: + expect = (GetSystemMetrics( SM_CXICON ) * 3) / 2; + break; + case SHIL_SYSSMALL: + expect = GetSystemMetrics( SM_CXSMICON ); + break; + case SHIL_JUMBO: + expect = 256; + break; + } + todo_wine_if(i == SHIL_SYSSMALL && dpi_aware && expect != GetSystemMetrics( SM_CXICON ) / 2) + { + ok( width == expect, "%d: got %d expect %d\n", i, width, expect ); + ok( height == expect, "%d: got %d expect %d\n", i, height, expect ); + } + IImageList_Release( list ); + } } START_TEST(shelllink) @@ -1347,6 +1403,7 @@ START_TEST(shelllink) HRESULT r; HMODULE hmod = GetModuleHandleA("shell32.dll"); HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); + HMODULE huser32 = GetModuleHandleA("user32.dll"); pILFree = (void *)GetProcAddress(hmod, (LPSTR)155); pILIsEqual = (void *)GetProcAddress(hmod, (LPSTR)21); @@ -1356,6 +1413,7 @@ START_TEST(shelllink) pGetLongPathNameA = (void *)GetProcAddress(hkernel32, "GetLongPathNameA"); pGetShortPathNameA = (void *)GetProcAddress(hkernel32, "GetShortPathNameA"); pSHExtractIconsW = (void *)GetProcAddress(hmod, "SHExtractIconsW"); + pIsProcessDPIAware = (void *)GetProcAddress(huser32, "IsProcessDPIAware"); r = CoInitialize(NULL); ok(r == S_OK, "CoInitialize failed (0x%08x)\n", r); -- 2.11.4.GIT