From 3458af7db00c4ba3efd4378d7f2190df62f29b95 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 13 Apr 2018 14:31:43 +0200 Subject: [PATCH] user32: Implement GetSystemMetricsForDpi(). Signed-off-by: Alexandre Julliard --- dlls/user32/sysparams.c | 112 +++++++++++++++++++++++++++++++++- dlls/user32/tests/sysparams.c | 81 ++++++++++++++++++++++++ dlls/user32/user32.spec | 1 + include/winuser.h | 1 + 4 files changed, 192 insertions(+), 3 deletions(-) diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 90a5413796e..425acaecc97 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -2539,10 +2539,10 @@ INT WINAPI GetSystemMetrics( INT index ) return ncm.iScrollHeight; case SM_CXICON: case SM_CYICON: - return MulDiv( 32, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ); + return map_to_dpi( 32, GetDpiForSystem() ); case SM_CXCURSOR: case SM_CYCURSOR: - ret = MulDiv( 32, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ); + ret = map_to_dpi( 32, GetDpiForSystem() ); if (ret >= 64) return 64; if (ret >= 48) return 48; return 32; @@ -2644,7 +2644,7 @@ INT WINAPI GetSystemMetrics( INT index ) return GetSystemMetrics(SM_CYMINIMIZED) + mm.iVertGap; case SM_CXSMICON: case SM_CYSMICON: - return MulDiv( 16, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ) & ~1; + return map_to_dpi( 16, GetDpiForSystem() ) & ~1; case SM_CYSMCAPTION: ncm.cbSize = sizeof(ncm); SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 ); @@ -2761,6 +2761,112 @@ INT WINAPI GetSystemMetrics( INT index ) } +/*********************************************************************** + * GetSystemMetricsForDpi (USER32.@) + */ +INT WINAPI GetSystemMetricsForDpi( INT index, UINT dpi ) +{ + NONCLIENTMETRICSW ncm; + ICONMETRICSW im; + UINT ret; + HDC hdc; + + /* some metrics are dynamic */ + switch (index) + { + case SM_CXVSCROLL: + case SM_CYHSCROLL: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iScrollWidth; + case SM_CYCAPTION: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iCaptionHeight + 1; + case SM_CYVTHUMB: + case SM_CXHTHUMB: + case SM_CYVSCROLL: + case SM_CXHSCROLL: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iScrollHeight; + case SM_CXICON: + case SM_CYICON: + return map_to_dpi( 32, dpi ); + case SM_CXCURSOR: + case SM_CYCURSOR: + ret = map_to_dpi( 32, dpi ); + if (ret >= 64) return 64; + if (ret >= 48) return 48; + return 32; + case SM_CYMENU: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iMenuHeight + 1; + case SM_CXSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iCaptionWidth; + case SM_CYSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iCaptionHeight; + case SM_CXFRAME: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return GetSystemMetricsForDpi( SM_CXDLGFRAME, dpi ) + ncm.iBorderWidth; + case SM_CYFRAME: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return GetSystemMetricsForDpi( SM_CYDLGFRAME, dpi ) + ncm.iBorderWidth; + case SM_CXICONSPACING: + im.cbSize = sizeof(im); + SystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im), &im, 0, dpi ); + return im.iHorzSpacing; + case SM_CYICONSPACING: + im.cbSize = sizeof(im); + SystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im), &im, 0, dpi ); + return im.iVertSpacing; + case SM_CXSMICON: + case SM_CYSMICON: + return map_to_dpi( 16, dpi ) & ~1; + case SM_CYSMCAPTION: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iSmCaptionHeight + 1; + case SM_CXSMSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iSmCaptionWidth; + case SM_CYSMSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iSmCaptionHeight; + case SM_CXMENUSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iMenuWidth; + case SM_CYMENUSIZE: + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + return ncm.iMenuHeight; + case SM_CXMENUCHECK: + case SM_CYMENUCHECK: + { + TEXTMETRICW tm; + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0, dpi ); + hdc = get_display_dc(); + get_text_metr_size( hdc, &ncm.lfMenuFont, &tm, NULL); + release_display_dc( hdc ); + return tm.tmHeight <= 0 ? 13 : ((tm.tmHeight + tm.tmExternalLeading - 1) | 1); + } + default: + return GetSystemMetrics( index ); + } +} + + /*********************************************************************** * SwapMouseButton (USER32.@) * Reverse or restore the meaning of the left and right mouse buttons diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c index fd006e34575..e662517d305 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 INT (WINAPI *pGetSystemMetricsForDpi)(INT,UINT); static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT); static BOOL strict; @@ -1473,6 +1474,18 @@ static int get_tmheight( LOGFONTA *plf, int flag) return tm.tmHeight + (flag ? tm.tmExternalLeading : 0); } +static int get_tmheightW( LOGFONTW *plf, int flag) +{ + TEXTMETRICW tm; + HDC hdc = GetDC(0); + HFONT hfont = CreateFontIndirectW( plf); + hfont = SelectObject( hdc, hfont); + GetTextMetricsW( hdc, &tm); + hfont = SelectObject( hdc, hfont); + ReleaseDC( 0, hdc ); + return tm.tmHeight + (flag ? tm.tmExternalLeading : 0); +} + static void test_GetSystemMetrics( void); static UINT smcxsmsize = 999999999; @@ -2934,6 +2947,73 @@ static void test_metrics_for_dpi( int custom_dpi ) ret = pSystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, sizeof(ncm2), &ncm2, FALSE, custom_dpi ); ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() ); + for (i = 0; i < 92; i++) + { + int ret1 = GetSystemMetrics( i ); + int ret2 = pGetSystemMetricsForDpi( i, custom_dpi ); + switch (i) + { + case SM_CXVSCROLL: + case SM_CYHSCROLL: + case SM_CYVTHUMB: + case SM_CXHTHUMB: + case SM_CXICON: + case SM_CYICON: + case SM_CYVSCROLL: + case SM_CXHSCROLL: + case SM_CYSIZE: + case SM_CXICONSPACING: + case SM_CYICONSPACING: + case SM_CXSMSIZE: + case SM_CYSMSIZE: + case SM_CYMENUSIZE: + ok( ret1 == MulDiv( ret2, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + case SM_CXSIZE: + ok( ret1 == ncm1.iCaptionWidth && ret2 == ncm2.iCaptionWidth, + "%u: wrong value %u vs %u caption %u vs %u\n", + i, ret1, ret2, ncm1.iCaptionWidth, ncm2.iCaptionWidth ); + break; + case SM_CXCURSOR: + case SM_CYCURSOR: + val = MulDiv( 32, custom_dpi, USER_DEFAULT_SCREEN_DPI ); + if (val < 48) val = 32; + else if (val < 64) val = 48; + else val = 64; + ok( val == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + case SM_CYCAPTION: + case SM_CYSMCAPTION: + case SM_CYMENU: + ok( ret1 - 1 == MulDiv( ret2 - 1, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + case SM_CXMENUSIZE: + ok( ret1 / 8 == MulDiv( ret2, dpi, custom_dpi ) / 8, "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + case SM_CXFRAME: + case SM_CYFRAME: + ok( ret1 == ncm1.iBorderWidth + 3 && ret2 == ncm2.iBorderWidth + 3, + "%u: wrong value %u vs %u borders %u+%u vs %u+%u\n", i, ret1, ret2, + ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth ); + break; + case SM_CXSMICON: + case SM_CYSMICON: + ok( ret1 == (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI ) & ~1) && + ret2 == (MulDiv( 16, custom_dpi, USER_DEFAULT_SCREEN_DPI ) & ~1), + "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + case SM_CXMENUCHECK: + case SM_CYMENUCHECK: + ok( ret1 == ((get_tmheightW( &ncm1.lfMenuFont, 1 ) - 1) | 1) && + ret2 == ((get_tmheightW( &ncm2.lfMenuFont, 1 ) - 1) | 1), + "%u: wrong value %u vs %u font %u vs %u\n", i, ret1, ret2, + get_tmheightW( &ncm1.lfMenuFont, 1 ), get_tmheightW( &ncm2.lfMenuFont, 1 )); + break; + default: + ok( ret1 == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 ); + break; + } + } im1.cbSize = sizeof(im1); ret = SystemParametersInfoW( SPI_GETICONMETRICS, sizeof(im1), &im1, FALSE ); ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() ); @@ -3376,6 +3456,7 @@ START_TEST(sysparams) pGetWindowDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetWindowDpiAwarenessContext"); pGetAwarenessFromDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetAwarenessFromDpiAwarenessContext"); pIsValidDpiAwarenessContext = (void*)GetProcAddress(hdll, "IsValidDpiAwarenessContext"); + pGetSystemMetricsForDpi = (void*)GetProcAddress(hdll, "GetSystemMetricsForDpi"); pSystemParametersInfoForDpi = (void*)GetProcAddress(hdll, "SystemParametersInfoForDpi"); hInstance = GetModuleHandleA( NULL ); diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 43352f94d9c..331451805ed 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -377,6 +377,7 @@ @ stdcall GetSysColorBrush(long) @ stdcall GetSystemMenu(long long) @ stdcall GetSystemMetrics(long) +@ stdcall GetSystemMetricsForDpi(long long) @ stdcall GetTabbedTextExtentA(long str long long ptr) @ stdcall GetTabbedTextExtentW(long wstr long long ptr) @ stdcall GetTaskmanWindow () diff --git a/include/winuser.h b/include/winuser.h index 11e3521d44a..ab3aba22c60 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -3762,6 +3762,7 @@ WINUSERAPI HBRUSH WINAPI GetSysColorBrush(INT); #define GetSysModalWindow() ((HWND)0) WINUSERAPI HMENU WINAPI GetSystemMenu(HWND,BOOL); WINUSERAPI INT WINAPI GetSystemMetrics(INT); +WINUSERAPI INT WINAPI GetSystemMetricsForDpi(INT,UINT); WINUSERAPI DWORD WINAPI GetTabbedTextExtentA(HDC,LPCSTR,INT,INT,const INT*); WINUSERAPI DWORD WINAPI GetTabbedTextExtentW(HDC,LPCWSTR,INT,INT,const INT*); #define GetTabbedTextExtent WINELIB_NAME_AW(GetTabbedTextExtent)