From a02ed147328e072574485bbd2bec320c630cb5c0 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 13 Apr 2018 14:18:15 +0200 Subject: [PATCH] user32: Implement SystemParametersInfoForDpi(). Signed-off-by: Alexandre Julliard --- dlls/user32/sysparams.c | 162 ++++++++++++++++++++++++++-------- dlls/user32/tests/sysparams.c | 99 ++++++++++++++++++++- dlls/user32/user32.spec | 1 + include/winuser.h | 1 + 4 files changed, 225 insertions(+), 38 deletions(-) diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 3ee07810256..90a5413796e 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -258,7 +258,7 @@ union sysparam_all_entry; struct sysparam_entry { - BOOL (*get)( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ); + BOOL (*get)( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ); BOOL (*set)( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT flags ); BOOL (*init)( union sysparam_all_entry *entry ); const WCHAR *regval; @@ -650,6 +650,19 @@ void release_display_dc( HDC hdc ) LeaveCriticalSection( &display_dc_section ); } +/* map value from system dpi to standard 96 dpi for storing in the registry */ +static int map_from_system_dpi( int val ) +{ + return MulDiv( val, USER_DEFAULT_SCREEN_DPI, GetDpiForSystem() ); +} + +/* map value from 96 dpi to system or custom dpi */ +static int map_to_dpi( int val, UINT dpi ) +{ + if (!dpi) dpi = GetDpiForSystem(); + return MulDiv( val, dpi, USER_DEFAULT_SCREEN_DPI ); +} + static INT CALLBACK real_fontname_proc(const LOGFONTW *lf, const TEXTMETRICW *ntm, DWORD type, LPARAM lparam) { const ENUMLOGFONTW *elf = (const ENUMLOGFONTW *)lf; @@ -706,7 +719,7 @@ static BOOL CALLBACK enum_monitors( HMONITOR monitor, HDC hdc, LPRECT rect, LPAR } /* load a uint parameter from the registry */ -static BOOL get_uint_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_uint_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -763,33 +776,45 @@ static BOOL init_int_entry( union sysparam_all_entry *entry ) } /* load a twips parameter from the registry */ -static BOOL get_twips_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_twips_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { + int val; + if (!ptr_param) return FALSE; if (!entry->hdr.loaded) { WCHAR buf[32]; - if (load_entry( &entry->hdr, buf, sizeof(buf) )) - { - int val = atoiW( buf ); - /* Dimensions are quoted as being "twips" values if negative and pixels if positive. - * One inch is 1440 twips. - * See for example - * Technical Reference to the Windows 2000 Registry -> - * HKEY_CURRENT_USER -> Control Panel -> Desktop -> WindowMetrics - */ - if (val < 0) val = (-val * GetDpiForSystem() + 720) / 1440; - entry->uint.val = val; - } + if (load_entry( &entry->hdr, buf, sizeof(buf) )) entry->uint.val = atoiW( buf ); } - *(UINT *)ptr_param = entry->uint.val; + + /* Dimensions are quoted as being "twips" values if negative and pixels if positive. + * One inch is 1440 twips. + * See for example + * Technical Reference to the Windows 2000 Registry -> + * HKEY_CURRENT_USER -> Control Panel -> Desktop -> WindowMetrics + */ + val = entry->uint.val; + if (val < 0) + val = MulDiv( -val, dpi, 1440 ); + else + val = map_to_dpi( val, dpi ); + + *(int *)ptr_param = val; return TRUE; } +/* set a twips parameter in the registry */ +static BOOL set_twips_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT flags ) +{ + int val = int_param; + if (val > 0) val = map_from_system_dpi( val ); + return set_int_entry( entry, val, ptr_param, flags ); +} + /* load a bool parameter from the registry */ -static BOOL get_bool_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_bool_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -825,7 +850,7 @@ static BOOL init_bool_entry( union sysparam_all_entry *entry ) } /* load a bool parameter using Yes/No strings from the registry */ -static BOOL get_yesno_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_yesno_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -857,7 +882,7 @@ static BOOL init_yesno_entry( union sysparam_all_entry *entry ) } /* load a dword (binary) parameter from the registry */ -static BOOL get_dword_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_dword_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -888,7 +913,7 @@ static BOOL init_dword_entry( union sysparam_all_entry *entry ) } /* load an RGB parameter from the registry */ -static BOOL get_rgb_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_rgb_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -952,25 +977,25 @@ static BOOL init_rgb_entry( union sysparam_all_entry *entry ) } /* load a font (binary) parameter from the registry */ -static BOOL get_font_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_font_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { + LOGFONTW font; + if (!ptr_param) return FALSE; if (!entry->hdr.loaded) { - LOGFONTW font; - switch (load_entry( &entry->hdr, &font, sizeof(font) )) { case sizeof(font): if (font.lfHeight > 0) /* positive height value means points ( inch/72 ) */ - font.lfHeight = -MulDiv( font.lfHeight, GetDpiForSystem(), 72 ); + font.lfHeight = -MulDiv( font.lfHeight, USER_DEFAULT_SCREEN_DPI, 72 ); entry->font.val = font; break; case sizeof(LOGFONT16): /* win9x-winME format */ SYSPARAMS_LogFont16To32W( (LOGFONT16 *)&font, &entry->font.val ); if (entry->font.val.lfHeight > 0) - entry->font.val.lfHeight = -MulDiv( entry->font.val.lfHeight, GetDpiForSystem(), 72 ); + entry->font.val.lfHeight = -MulDiv( entry->font.val.lfHeight, USER_DEFAULT_SCREEN_DPI, 72 ); break; default: WARN( "Unknown format in key %s value %s\n", @@ -979,13 +1004,16 @@ static BOOL get_font_entry( union sysparam_all_entry *entry, UINT int_param, voi /* fall through */ case 0: /* use the default GUI font */ GetObjectW( GetStockObject( DEFAULT_GUI_FONT ), sizeof(font), &font ); + font.lfHeight = map_from_system_dpi( font.lfHeight ); font.lfWeight = entry->font.weight; entry->font.val = font; break; } entry->hdr.loaded = TRUE; } - *(LOGFONTW *)ptr_param = entry->font.val; + font = entry->font.val; + font.lfHeight = map_to_dpi( font.lfHeight, dpi ); + *(LOGFONTW *)ptr_param = font; return TRUE; } @@ -999,6 +1027,7 @@ static BOOL set_font_entry( union sysparam_all_entry *entry, UINT int_param, voi /* zero pad the end of lfFaceName so we don't save uninitialised data */ ptr = memchrW( font.lfFaceName, 0, LF_FACESIZE ); if (ptr) memset( ptr, 0, (font.lfFaceName + LF_FACESIZE - ptr) * sizeof(WCHAR) ); + font.lfHeight = map_from_system_dpi( font.lfHeight ); if (!save_entry( &entry->hdr, &font, sizeof(font), REG_BINARY, flags )) return FALSE; entry->font.val = font; @@ -1010,12 +1039,13 @@ static BOOL set_font_entry( union sysparam_all_entry *entry, UINT int_param, voi static BOOL init_font_entry( union sysparam_all_entry *entry ) { GetObjectW( GetStockObject( DEFAULT_GUI_FONT ), sizeof(entry->font.val), &entry->font.val ); + entry->font.val.lfHeight = map_from_system_dpi( entry->font.val.lfHeight ); entry->font.val.lfWeight = entry->font.weight; return init_entry( &entry->hdr, &entry->font.val, sizeof(entry->font.val), REG_BINARY ); } /* get a path parameter in the registry */ -static BOOL get_path_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_path_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -1053,7 +1083,7 @@ static BOOL init_path_entry( union sysparam_all_entry *entry ) } /* get a binary parameter in the registry */ -static BOOL get_binary_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_binary_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { if (!ptr_param) return FALSE; @@ -1098,14 +1128,14 @@ static BOOL init_binary_entry( union sysparam_all_entry *entry ) } /* get a user pref parameter in the registry */ -static BOOL get_userpref_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param ) +static BOOL get_userpref_entry( union sysparam_all_entry *entry, UINT int_param, void *ptr_param, UINT dpi ) { union sysparam_all_entry *parent_entry = (union sysparam_all_entry *)entry->pref.parent; BYTE prefs[8]; if (!ptr_param) return FALSE; - if (!parent_entry->hdr.get( parent_entry, sizeof(prefs), prefs )) return FALSE; + if (!parent_entry->hdr.get( parent_entry, sizeof(prefs), prefs, dpi )) return FALSE; *(BOOL *)ptr_param = (prefs[entry->pref.offset] & entry->pref.mask) != 0; return TRUE; } @@ -1117,7 +1147,7 @@ static BOOL set_userpref_entry( union sysparam_all_entry *entry, UINT int_param, BYTE prefs[8]; parent_entry->hdr.loaded = FALSE; /* force loading it again */ - if (!parent_entry->hdr.get( parent_entry, sizeof(prefs), prefs )) return FALSE; + if (!parent_entry->hdr.get( parent_entry, sizeof(prefs), prefs, GetDpiForSystem() )) return FALSE; if (PtrToUlong( ptr_param )) prefs[entry->pref.offset] |= entry->pref.mask; else prefs[entry->pref.offset] &= ~entry->pref.mask; @@ -1125,10 +1155,15 @@ static BOOL set_userpref_entry( union sysparam_all_entry *entry, UINT int_param, return parent_entry->hdr.set( parent_entry, sizeof(prefs), prefs, flags ); } -static BOOL get_entry( void *ptr, UINT int_param, void *ptr_param ) +static BOOL get_entry_dpi( void *ptr, UINT int_param, void *ptr_param, UINT dpi ) { union sysparam_all_entry *entry = ptr; - return entry->hdr.get( entry, int_param, ptr_param ); + return entry->hdr.get( entry, int_param, ptr_param, dpi ); +} + +static BOOL get_entry( void *ptr, UINT int_param, void *ptr_param ) +{ + return get_entry_dpi( ptr, int_param, ptr_param, GetDpiForSystem() ); } static BOOL set_entry( void *ptr, UINT int_param, void *ptr_param, UINT flags ) @@ -1162,7 +1197,7 @@ static BOOL set_entry( void *ptr, UINT int_param, void *ptr_param, UINT flags ) name ##_VALNAME }, (val) } #define TWIPS_ENTRY(name,val) \ - struct sysparam_uint_entry entry_##name = { { get_twips_entry, set_int_entry, init_int_entry, \ + struct sysparam_uint_entry entry_##name = { { get_twips_entry, set_twips_entry, init_int_entry, \ name ##_VALNAME }, (val) } #define DWORD_ENTRY(name,val) \ @@ -1430,6 +1465,61 @@ static BOOL update_desktop_wallpaper(void) return TRUE; } + +/*********************************************************************** + * SystemParametersInfoForDpi (USER32.@) + */ +BOOL WINAPI SystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi ) +{ + BOOL ret = FALSE; + + switch (action) + { + case SPI_GETICONTITLELOGFONT: + ret = get_entry_dpi( &entry_ICONTITLELOGFONT, val, ptr, dpi ); + break; + case SPI_GETNONCLIENTMETRICS: + { + NONCLIENTMETRICSW *ncm = ptr; + + if (!ncm) break; + ret = get_entry_dpi( &entry_BORDER, 0, &ncm->iBorderWidth, dpi ) && + get_entry_dpi( &entry_SCROLLWIDTH, 0, &ncm->iScrollWidth, dpi ) && + get_entry_dpi( &entry_SCROLLHEIGHT, 0, &ncm->iScrollHeight, dpi ) && + get_entry_dpi( &entry_CAPTIONWIDTH, 0, &ncm->iCaptionWidth, dpi ) && + get_entry_dpi( &entry_CAPTIONHEIGHT, 0, &ncm->iCaptionHeight, dpi ) && + get_entry_dpi( &entry_CAPTIONLOGFONT, 0, &ncm->lfCaptionFont, dpi ) && + get_entry_dpi( &entry_SMCAPTIONWIDTH, 0, &ncm->iSmCaptionWidth, dpi ) && + get_entry_dpi( &entry_SMCAPTIONHEIGHT, 0, &ncm->iSmCaptionHeight, dpi ) && + get_entry_dpi( &entry_SMCAPTIONLOGFONT, 0, &ncm->lfSmCaptionFont, dpi ) && + get_entry_dpi( &entry_MENUWIDTH, 0, &ncm->iMenuWidth, dpi ) && + get_entry_dpi( &entry_MENUHEIGHT, 0, &ncm->iMenuHeight, dpi ) && + get_entry_dpi( &entry_MENULOGFONT, 0, &ncm->lfMenuFont, dpi ) && + get_entry_dpi( &entry_STATUSLOGFONT, 0, &ncm->lfStatusFont, dpi ) && + get_entry_dpi( &entry_MESSAGELOGFONT, 0, &ncm->lfMessageFont, dpi ); + if (ret && ncm->cbSize == sizeof(NONCLIENTMETRICSW)) + ret = get_entry_dpi( &entry_PADDEDBORDERWIDTH, 0, &ncm->iPaddedBorderWidth, dpi ); + normalize_nonclientmetrics( ncm ); + break; + } + case SPI_GETICONMETRICS: + { + ICONMETRICSW *im = ptr; + if (im && im->cbSize == sizeof(*im)) + ret = get_entry_dpi( &entry_ICONHORIZONTALSPACING, 0, &im->iHorzSpacing, dpi ) && + get_entry_dpi( &entry_ICONVERTICALSPACING, 0, &im->iVertSpacing, dpi ) && + get_entry_dpi( &entry_ICONTITLEWRAP, 0, &im->iTitleWrap, dpi ) && + get_entry_dpi( &entry_ICONTITLELOGFONT, 0, &im->lfFont, dpi ); + break; + } + default: + SetLastError( ERROR_INVALID_PARAMETER ); + break; + } + return ret; +} + + /*********************************************************************** * SystemParametersInfoW (USER32.@) * @@ -1520,7 +1610,7 @@ BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam, ret = get_entry( &entry_ICONHORIZONTALSPACING, uiParam, pvParam ); else { - int min_val = MulDiv( 32, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ); + int min_val = map_to_dpi( 32, GetDpiForSystem() ); ret = set_entry( &entry_ICONHORIZONTALSPACING, max( min_val, uiParam ), pvParam, fWinIni ); } break; @@ -1561,7 +1651,7 @@ BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam, ret = get_entry( &entry_ICONVERTICALSPACING, uiParam, pvParam ); else { - int min_val = MulDiv( 32, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ); + int min_val = map_to_dpi( 32, GetDpiForSystem() ); ret = set_entry( &entry_ICONVERTICALSPACING, max( min_val, uiParam ), pvParam, fWinIni ); } break; diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c index 95273f2bb9b..fd006e34575 100644 --- a/dlls/user32/tests/sysparams.c +++ b/dlls/user32/tests/sysparams.c @@ -50,6 +50,7 @@ static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENE static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND); static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); static BOOL (WINAPI *pIsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); +static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT); static BOOL strict; static int dpi, real_dpi; @@ -1507,7 +1508,6 @@ static void test_SPI_SETNONCLIENTMETRICS( void ) /* 44 */ Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi); /* test registry entries */ TEST_NONCLIENTMETRICS_REG( Ncmorig); - Ncmorig.lfCaptionFont.lfHeight = MulDiv( Ncmorig.lfCaptionFont.lfHeight, real_dpi, dpi ); /* make small changes */ Ncmnew = Ncmstart; @@ -2900,6 +2900,98 @@ static void test_GetSystemMetrics( void) DeleteDC(hdc); } +static void compare_font( const LOGFONTW *lf1, const LOGFONTW *lf2, int dpi, int custom_dpi, int line ) +{ + ok_(__FILE__,line)( lf1->lfHeight == MulDiv( lf2->lfHeight, dpi, custom_dpi ), + "wrong lfHeight %d vs %d\n", lf1->lfHeight, lf2->lfHeight ); + ok_(__FILE__,line)( abs( lf1->lfWidth - MulDiv( lf2->lfWidth, dpi, custom_dpi )) <= 1, + "wrong lfWidth %d vs %d\n", lf1->lfWidth, lf2->lfWidth ); + ok_(__FILE__,line)( !memcmp( &lf1->lfEscapement, &lf2->lfEscapement, + offsetof( LOGFONTW, lfFaceName ) - offsetof( LOGFONTW, lfEscapement )), + "font differs\n" ); + ok_(__FILE__,line)( !lstrcmpW( lf1->lfFaceName, lf2->lfFaceName ), "wrong face name %s vs %s\n", + wine_dbgstr_w( lf1->lfFaceName ), wine_dbgstr_w( lf2->lfFaceName )); +} + +static void test_metrics_for_dpi( int custom_dpi ) +{ + int i, val; + NONCLIENTMETRICSW ncm1, ncm2; + ICONMETRICSW im1, im2; + LOGFONTW lf1, lf2; + BOOL ret; + + if (!pSystemParametersInfoForDpi) + { + win_skip( "custom dpi metrics not supported\n" ); + return; + } + + ncm1.cbSize = sizeof(ncm1); + ret = SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof(ncm1), &ncm1, FALSE ); + ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() ); + ncm2.cbSize = sizeof(ncm2); + ret = pSystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, sizeof(ncm2), &ncm2, FALSE, custom_dpi ); + ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() ); + + im1.cbSize = sizeof(im1); + ret = SystemParametersInfoW( SPI_GETICONMETRICS, sizeof(im1), &im1, FALSE ); + ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() ); + im2.cbSize = sizeof(im2); + ret = pSystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im2), &im2, FALSE, custom_dpi ); + ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() ); + ok( im1.iHorzSpacing == MulDiv( im2.iHorzSpacing, dpi, custom_dpi ), "wrong iHorzSpacing %u vs %u\n", + im1.iHorzSpacing, im2.iHorzSpacing ); + ok( im1.iVertSpacing == MulDiv( im2.iVertSpacing, dpi, custom_dpi ), "wrong iVertSpacing %u vs %u\n", + im1.iVertSpacing, im2.iVertSpacing ); + ok( im1.iTitleWrap == im2.iTitleWrap, "wrong iTitleWrap %u vs %u\n", + im1.iTitleWrap, im2.iTitleWrap ); + compare_font( &im1.lfFont, &im2.lfFont, dpi, custom_dpi, __LINE__ ); + + ret = SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf1), &lf1, FALSE ); + ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() ); + ret = pSystemParametersInfoForDpi( SPI_GETICONTITLELOGFONT, sizeof(lf2), &lf2, FALSE, custom_dpi ); + ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() ); + compare_font( &lf1, &lf2, dpi, custom_dpi, __LINE__ ); + + /* on high-dpi iPaddedBorderWidth is used in addition to iBorderWidth */ + ok( ncm1.iBorderWidth + ncm1.iPaddedBorderWidth == MulDiv( ncm2.iBorderWidth + ncm2.iPaddedBorderWidth, dpi, custom_dpi ), + "wrong iBorderWidth %u+%u vs %u+%u\n", + ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth ); + ok( ncm1.iScrollWidth == MulDiv( ncm2.iScrollWidth, dpi, custom_dpi ), + "wrong iScrollWidth %u vs %u\n", ncm1.iScrollWidth, ncm2.iScrollWidth ); + ok( ncm1.iScrollHeight == MulDiv( ncm2.iScrollHeight, dpi, custom_dpi ), + "wrong iScrollHeight %u vs %u\n", ncm1.iScrollHeight, ncm2.iScrollHeight ); + ok( ((ncm1.iCaptionWidth + 1) & ~1) == ((MulDiv( ncm2.iCaptionWidth, dpi, custom_dpi ) + 1) & ~1), + "wrong iCaptionWidth %u vs %u\n", ncm1.iCaptionWidth, ncm2.iCaptionWidth ); + ok( ncm1.iCaptionHeight == MulDiv( ncm2.iCaptionHeight, dpi, custom_dpi ), + "wrong iCaptionHeight %u vs %u\n", ncm1.iCaptionHeight, ncm2.iCaptionHeight ); + compare_font( &ncm1.lfCaptionFont, &ncm2.lfCaptionFont, dpi, custom_dpi, __LINE__ ); + ok( ncm1.iSmCaptionHeight == MulDiv( ncm2.iSmCaptionHeight, dpi, custom_dpi ), + "wrong iSmCaptionHeight %u vs %u\n", ncm1.iSmCaptionHeight, ncm2.iSmCaptionHeight ); + compare_font( &ncm1.lfSmCaptionFont, &ncm2.lfSmCaptionFont, dpi, custom_dpi, __LINE__ ); + ok( ncm1.iMenuHeight == MulDiv( ncm2.iMenuHeight, dpi, custom_dpi ), + "wrong iMenuHeight %u vs %u\n", ncm1.iMenuHeight, ncm2.iMenuHeight ); + /* iSmCaptionWidth and iMenuWidth apparently need to be multiples of 8 */ + ok( ncm1.iSmCaptionWidth / 8 == MulDiv( ncm2.iSmCaptionWidth, dpi, custom_dpi ) / 8, + "wrong iSmCaptionWidth %u vs %u\n", ncm1.iSmCaptionWidth, ncm2.iSmCaptionWidth ); + ok( ncm1.iMenuWidth / 8 == MulDiv( ncm2.iMenuWidth, dpi, custom_dpi ) / 8, + "wrong iMenuWidth %u vs %u\n", ncm1.iMenuWidth, ncm2.iMenuWidth ); + compare_font( &ncm1.lfMenuFont, &ncm2.lfMenuFont, dpi, custom_dpi, __LINE__ ); + compare_font( &ncm1.lfStatusFont, &ncm2.lfStatusFont, dpi, custom_dpi, __LINE__ ); + compare_font( &ncm1.lfMessageFont, &ncm2.lfMessageFont, dpi, custom_dpi, __LINE__ ); + + for (i = 1; i < 120; i++) + { + if (i == SPI_GETICONTITLELOGFONT || i == SPI_GETNONCLIENTMETRICS || i == SPI_GETICONMETRICS) + continue; + SetLastError( 0xdeadbeef ); + ret = pSystemParametersInfoForDpi( i, 0, &val, 0, custom_dpi ); + ok( !ret, "%u: SystemParametersInfoForDpi succeeded\n", i ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "%u: wrong error %u\n", i, GetLastError() ); + } +} + static void test_EnumDisplaySettings(void) { DEVMODEA devmode; @@ -3199,6 +3291,8 @@ static void test_dpi_aware(void) if (pGetDpiForSystem) real_dpi = pGetDpiForSystem(); dpi = real_dpi; test_GetSystemMetrics(); + test_metrics_for_dpi( 96 ); + test_metrics_for_dpi( 192 ); } static void test_window_dpi(void) @@ -3282,6 +3376,7 @@ START_TEST(sysparams) pGetWindowDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetWindowDpiAwarenessContext"); pGetAwarenessFromDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetAwarenessFromDpiAwarenessContext"); pIsValidDpiAwarenessContext = (void*)GetProcAddress(hdll, "IsValidDpiAwarenessContext"); + pSystemParametersInfoForDpi = (void*)GetProcAddress(hdll, "SystemParametersInfoForDpi"); hInstance = GetModuleHandleA( NULL ); hdc = GetDC(0); @@ -3300,7 +3395,7 @@ START_TEST(sysparams) trace("testing GetSystemMetrics with your current desktop settings\n"); test_GetSystemMetrics( ); - trace("testing EnumDisplaySettings vs GetDeviceCaps\n"); + test_metrics_for_dpi( 192 ); test_EnumDisplaySettings( ); test_GetSysColorBrush( ); diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index bdecc6ee487..43352f94d9c 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -737,6 +737,7 @@ @ stdcall SwitchToThisWindow(long long) # @ stub SysErrorBox @ stdcall SystemParametersInfoA(long long ptr long) +@ stdcall SystemParametersInfoForDpi(long long ptr long long) @ stdcall SystemParametersInfoW(long long ptr long) @ stdcall TabbedTextOutA(long long long str long long ptr long) @ stdcall TabbedTextOutW(long long long wstr long long ptr long) diff --git a/include/winuser.h b/include/winuser.h index d35c4459f19..11e3521d44a 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -4129,6 +4129,7 @@ WINUSERAPI VOID WINAPI SwitchToThisWindow(HWND,BOOL); WINUSERAPI BOOL WINAPI SystemParametersInfoA(UINT,UINT,LPVOID,UINT); WINUSERAPI BOOL WINAPI SystemParametersInfoW(UINT,UINT,LPVOID,UINT); #define SystemParametersInfo WINELIB_NAME_AW(SystemParametersInfo) +WINUSERAPI BOOL WINAPI SystemParametersInfoForDpi(UINT,UINT,void*,UINT,UINT); WINUSERAPI LONG WINAPI TabbedTextOutA(HDC,INT,INT,LPCSTR,INT,INT,const INT*,INT); WINUSERAPI LONG WINAPI TabbedTextOutW(HDC,INT,INT,LPCWSTR,INT,INT,const INT*,INT); #define TabbedTextOut WINELIB_NAME_AW(TabbedTextOut)