GetSystemMetrics tweaks with tests

Rein Klazes wijn at wanadoo.nl
Wed Jun 29 12:39:30 CDT 2005


Hi,

Changelog:

dlls/user	: sysparams.c
dlls/user/tests	: sysparams.c

- add a bunch of GetSystemMetrics tests;
- Fix GetSystemMetrics() as the result from running those tests on
Windows 95, ME, NT4, 2K and XP.

Rein.
-------------- next part --------------
--- wine/dlls/user/sysparams.c	2005-06-29 08:57:14.000000000 +0200
+++ mywine/dlls/user/sysparams.c	2005-06-29 16:52:19.000000000 +0200
@@ -582,6 +582,24 @@ static void SYSPARAMS_SetSysColor( int i
     __wine_make_gdi_object_system( SysColorPens[index], TRUE);
 }
 
+void SYSPARAMS_gettextmetric( HDC hdc, LOGFONTW *plf, TEXTMETRICW * ptm, SIZE *psz)
+{
+    HFONT hfont, hfontsav;
+    hfont = CreateFontIndirectW( plf);
+    if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
+        ptm->tmHeight = -1;
+        ptm->tmExternalLeading = -1;
+        if( hfont) DeleteObject( hfont);
+        return;
+    }
+    GetTextMetricsW( hdc, ptm);
+    if( psz) {
+        if( !DIALOG_GetCharSize( hdc, hfont, psz))
+            psz->cx = 10;
+    }
+    SelectObject( hdc, hfontsav);
+    DeleteObject( hfont);
+}
 
 /***********************************************************************
  *           SYSPARAMS_Init
@@ -605,11 +623,15 @@ void SYSPARAMS_Init(void)
 {
     HKEY hkey; /* key to the window metrics area of the registry */
     WCHAR buf[10];
-    INT border;
     CPINFO cpinfo;
     int i, r, g, b, dpi;
     char buffer[100];
     HBITMAP h55AABitmap;
+    INT BorderWidth, ScrollHeight, ScrollWidth, CaptionHeight, CaptionWidth, MenuHeight, MenuWidth,
+        SmCaptionHeight, SmCaptionWidth;
+    TEXTMETRICW tmCaptionFont, tmSmCaptionFont, tmMenuFont;
+    NONCLIENTMETRICSW ncm;
+    SIZE CaptionFontAvCharSz;
 
 
     display_dc = CreateICW( DISPLAY, NULL, NULL, NULL );
@@ -619,22 +641,42 @@ void SYSPARAMS_Init(void)
     if (RegOpenKeyExW (HKEY_CURRENT_USER, METRICS_REGKEY,
                        0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) hkey = 0;
 
-    sysMetrics[SM_CXVSCROLL] = SYSPARAMS_GetRegistryMetric( hkey, METRICS_SCROLLWIDTH_VALNAME, 16 , dpi);
-    sysMetrics[SM_CYHSCROLL] = sysMetrics[SM_CXVSCROLL];
-
+    BorderWidth = SYSPARAMS_GetRegistryMetric( hkey, METRICS_BORDERWIDTH_VALNAME, 1, dpi);
+    ScrollHeight = SYSPARAMS_GetRegistryMetric (hkey, METRICS_SCROLLHEIGHT_VALNAME, 16, dpi);
+    ScrollWidth = SYSPARAMS_GetRegistryMetric( hkey, METRICS_SCROLLWIDTH_VALNAME, ScrollHeight , dpi);
+    CaptionHeight = SYSPARAMS_GetRegistryMetric(hkey, METRICS_CAPTIONHEIGHT_VALNAME, 18, dpi);
+    CaptionWidth = SYSPARAMS_GetRegistryMetric (hkey, METRICS_CAPTIONWIDTH_VALNAME, CaptionHeight, dpi);
+    MenuHeight = SYSPARAMS_GetRegistryMetric (hkey, METRICS_MENUHEIGHT_VALNAME, 18, dpi);
+    MenuWidth = SYSPARAMS_GetRegistryMetric(hkey, METRICS_MENUWIDTH_VALNAME, MenuHeight, dpi);
+    SmCaptionHeight = SYSPARAMS_GetRegistryMetric(hkey, METRICS_SMCAPTIONHEIGHT_VALNAME, 15, dpi);
+    SmCaptionWidth = SYSPARAMS_GetRegistryMetric (hkey, METRICS_SMCAPTIONWIDTH_VALNAME, SmCaptionHeight, dpi);
+    /* lo-limit some parameters as Windows does */
+    if( CaptionWidth < 8 ) CaptionWidth = 8;
+    if( ScrollWidth < 8 ) ScrollWidth = 8;
+    if( ScrollHeight < 8 ) ScrollHeight = 8;
+    if( MenuWidth < 8 ) MenuWidth = 8; /* not on Win9x */
+    /* get logfonts for MenuFont, CaptionFont and SmCaptionFont
+     * ( FIXME: optimize this ) */
+    ncm.cbSize = sizeof(ncm);
+    SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
+    /* and get the needed metrics from those */
+    SYSPARAMS_gettextmetric( display_dc, & ncm.lfMenuFont, &tmMenuFont, NULL);
+    SYSPARAMS_gettextmetric( display_dc, & ncm.lfCaptionFont, &tmCaptionFont, &CaptionFontAvCharSz);
+    SYSPARAMS_gettextmetric( display_dc, & ncm.lfSmCaptionFont, &tmSmCaptionFont, NULL);
+  
     /* The Win 2000 resource kit SAYS that this is governed by the ScrollHeight
      * but on my computer that controls the CYV/CXH values. */
-    sysMetrics[SM_CYCAPTION] = SYSPARAMS_GetRegistryMetric(hkey, METRICS_CAPTIONHEIGHT_VALNAME, 18, dpi)
-                                 + 1; /* for the separator? */
-
-    sysMetrics[SM_CYMENU] = SYSPARAMS_GetRegistryMetric (hkey, METRICS_MENUHEIGHT_VALNAME, 18, dpi) + 1;
+    sysMetrics[SM_CXVSCROLL] = ScrollWidth;
+    sysMetrics[SM_CYHSCROLL] = sysMetrics[SM_CXVSCROLL];
 
+    sysMetrics[SM_CYCAPTION] = max( CaptionHeight + 1, tmCaptionFont.tmHeight + 3);
+    sysMetrics[SM_CYMENU] = max( MenuHeight + 1,
+            tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading + 3);
     sysMetrics[SM_CXDLGFRAME] = 3;
     sysMetrics[SM_CYDLGFRAME] = sysMetrics[SM_CXDLGFRAME];
 
-    SystemParametersInfoW( SPI_GETBORDER, 0, &border, 0 );
-    sysMetrics[SM_CXFRAME] = sysMetrics[SM_CXDLGFRAME] + border;
-    sysMetrics[SM_CYFRAME] = sysMetrics[SM_CYDLGFRAME] + border;
+    sysMetrics[SM_CXFRAME] = max( sysMetrics[SM_CXDLGFRAME] + BorderWidth, 4);
+    sysMetrics[SM_CYFRAME] = max( sysMetrics[SM_CYDLGFRAME] + BorderWidth, 4);
 
     sysMetrics[SM_CXCURSOR] = 32;
     sysMetrics[SM_CYCURSOR] = 32;
@@ -645,12 +687,12 @@ void SYSPARAMS_Init(void)
 
     sysMetrics[SM_CYVTHUMB] = sysMetrics[SM_CXVSCROLL];
     sysMetrics[SM_CXHTHUMB] = sysMetrics[SM_CYVTHUMB];
-    sysMetrics[SM_CXICON] = SYSPARAMS_GetRegistryMetric( hkey, METRICS_ICONSIZE_VALNAME, 32 , dpi);
+    sysMetrics[SM_CXICON] = 32;
     sysMetrics[SM_CYICON] = sysMetrics[SM_CXICON];
     sysMetrics[SM_CYKANJIWINDOW] = 0;
     sysMetrics[SM_MOUSEPRESENT] = 1;
-    sysMetrics[SM_CYVSCROLL] = SYSPARAMS_GetRegistryMetric (hkey, METRICS_SCROLLHEIGHT_VALNAME, sysMetrics[SM_CXVSCROLL], dpi);
-    sysMetrics[SM_CXHSCROLL] = SYSPARAMS_GetRegistryMetric (hkey, METRICS_SCROLLHEIGHT_VALNAME, sysMetrics[SM_CYHSCROLL], dpi);
+    sysMetrics[SM_CYVSCROLL] = ScrollHeight;
+    sysMetrics[SM_CXHSCROLL] = ScrollHeight;
     sysMetrics[SM_DEBUG] = 0;
 
     sysMetrics[SM_SWAPBUTTON] = 0;
@@ -662,13 +704,17 @@ void SYSPARAMS_Init(void)
     sysMetrics[SM_RESERVED2] = 0;
     sysMetrics[SM_RESERVED3] = 0;
     sysMetrics[SM_RESERVED4] = 0;
-
-    /* FIXME: The following two are calculated, but how? */
-    sysMetrics[SM_CXMIN] = 112;
-    sysMetrics[SM_CYMIN] = 27;
-
-    sysMetrics[SM_CXSIZE] = SYSPARAMS_GetRegistryMetric (hkey, METRICS_CAPTIONWIDTH_VALNAME, sysMetrics[SM_CYCAPTION] - 1, dpi);
+    
+    sysMetrics[SM_CXSIZE] = CaptionWidth; /* classic/standard windows style.
+                                             XP windows style makes it equal
+                                             to sysMetrics[SM_CYSIZE] */
     sysMetrics[SM_CYSIZE] = sysMetrics[SM_CYCAPTION] - 1;
+ 
+    sysMetrics[SM_CXMIN] = 3 * CaptionWidth + sysMetrics[ SM_CYSIZE] + 4 +
+        4 * CaptionFontAvCharSz.cx + 2 * sysMetrics[ SM_CXFRAME];
+    
+    sysMetrics[SM_CYMIN] = sysMetrics[SM_CYCAPTION] + 2 * sysMetrics[SM_CYFRAME] ;
+
     sysMetrics[SM_CXMINTRACK] = sysMetrics[SM_CXMIN];
     sysMetrics[SM_CYMINTRACK] = sysMetrics[SM_CYMIN];
 
@@ -703,16 +749,17 @@ void SYSPARAMS_Init(void)
     sysMetrics[SM_CYMINSPACING] = 24;
     sysMetrics[SM_CXSMICON] = 16;
     sysMetrics[SM_CYSMICON] = 16;
-    sysMetrics[SM_CYSMCAPTION] = SYSPARAMS_GetRegistryMetric(hkey, METRICS_SMCAPTIONHEIGHT_VALNAME, 15, dpi) + 1;
-    sysMetrics[SM_CXSMSIZE] = SYSPARAMS_GetRegistryMetric(hkey, METRICS_SMCAPTIONWIDTH_VALNAME, 13, dpi);
+    sysMetrics[SM_CYSMCAPTION] = max( SmCaptionHeight + 1, tmSmCaptionFont.tmHeight + 3);
+    sysMetrics[SM_CXSMSIZE] = SmCaptionWidth;
     sysMetrics[SM_CYSMSIZE] = sysMetrics[SM_CYSMCAPTION] - 1;
-    sysMetrics[SM_CXMENUSIZE] = SYSPARAMS_GetRegistryMetric(hkey, METRICS_MENUWIDTH_VALNAME, sysMetrics[SM_CYMENU] - 1, dpi);
+    sysMetrics[SM_CXMENUSIZE] = MenuWidth;
     sysMetrics[SM_CYMENUSIZE] = sysMetrics[SM_CYMENU] - 1;
 
     /* FIXME: What do these mean? */
     sysMetrics[SM_ARRANGE] = ARW_HIDE;
     sysMetrics[SM_CXMINIMIZED] = 160;
-    sysMetrics[SM_CYMINIMIZED] = 24;
+
+    sysMetrics[SM_CYMINIMIZED] = sysMetrics[SM_CYCAPTION] + 5;
 
     /* FIXME: How do I calculate these? */
     sysMetrics[SM_NETWORK] = 3;
@@ -722,8 +769,9 @@ void SYSPARAMS_Init(void)
 
     sysMetrics[SM_CXDRAG] = 4;
     sysMetrics[SM_CYDRAG] = 4;
-    sysMetrics[SM_CXMENUCHECK] = 13;
-    sysMetrics[SM_CYMENUCHECK] = 13;
+    sysMetrics[SM_CXMENUCHECK] = tmMenuFont.tmHeight <= 0 ? 13 :
+        ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1;
+    sysMetrics[SM_CYMENUCHECK] = sysMetrics[SM_CXMENUCHECK];
 
     /* FIXME: Should check the type of processor for the following */
     sysMetrics[SM_SLOWMACHINE] = 0;
@@ -2777,6 +2825,8 @@ BOOL WINAPI SystemParametersInfoA( UINT 
 INT WINAPI GetSystemMetrics( INT index )
 {
     /* some metrics are dynamic */
+    /* FIXME: some metrics ( SM_C?FULLSCREEN, SM_C?MAXIMIZED ) depend on the presence
+     * of application toolbars. Need to query window manager to get that right. */
     switch (index)
     {
     case SM_CXSCREEN:
@@ -2797,7 +2847,7 @@ INT WINAPI GetSystemMetrics( INT index )
     case SM_CXMAXIMIZED:
         return GetDeviceCaps( display_dc, HORZRES ) + 2 * sysMetrics[SM_CXFRAME];
     case SM_CYMAXIMIZED:
-        return GetDeviceCaps( display_dc, VERTRES ) + 2 * sysMetrics[SM_CYFRAME];
+        return GetDeviceCaps( display_dc, VERTRES ) - sysMetrics[SM_CYCAPTION] + sysMetrics[SM_CYMIN];
 
     default:
         if ((index < 0) || (index > SM_CMETRICS)) return 0;
--- wine/dlls/user/tests/sysparams.c	2005-06-21 10:01:36.000000000 +0200
+++ mywine/dlls/user/tests/sysparams.c	2005-06-29 16:28:42.000000000 +0200
@@ -1690,6 +1690,379 @@ static DWORD WINAPI SysParamsThreadFunc(
     return 0;
 }
 
+/* test calculation of GetSystemMetrics values from the values
+ * under HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics.
+ * There is an command line argument to perform multiple tests
+ * with random values.
+ */
+typedef struct
+{
+    INT16  lfHeight;
+    INT16  lfWidth;
+    INT16  lfEscapement;
+    INT16  lfOrientation;
+    INT16  lfWeight;
+    BYTE   lfItalic;
+    BYTE   lfUnderline;
+    BYTE   lfStrikeOut;
+    BYTE   lfCharSet;
+    BYTE   lfOutPrecision;
+    BYTE   lfClipPrecision;
+    BYTE   lfQuality;
+    BYTE   lfPitchAndFamily;
+    CHAR   lfFaceName[LF_FACESIZE];
+} LOGFONT16, *LPLOGFONT16;
+
+/* get an integer value from the registry on behalf of the GetSystemMetrics
+ * tests */
+INT gsm_valfromreg( HKEY hkey, char *valname, int dpi)
+{
+    char buf[64];
+    DWORD ret;
+    DWORD size, type;
+    int value;
+    size = sizeof(buf);
+    ret=RegQueryValueExA( hkey, valname, NULL, &type, buf, &size );
+    if( ret != ERROR_SUCCESS) return -1;
+    value = atoi( buf);
+    if( value < 0)
+        value = ( -value * dpi + 720) / 1440;
+    return value;
+}
+
+/* get font metrics from the registry on behalf of the GetSystemMetrics
+ * tests */
+int gsm_tmfromreg( HKEY hkey, HDC hdc,  char *val, TEXTMETRICA *ptm, INT* avcw
+                  , int dpi)
+{
+    LOGFONTW lfw;
+    DWORD ret, size, type;
+    HFONT hfont;
+    char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    SIZE sz;
+
+    size = sizeof( lfw);
+    ret=RegQueryValueExA( hkey, val, NULL, &type, (char *) &lfw, &size );
+    if( ret != ERROR_SUCCESS) {
+        trace( "Key HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics value %s not available.\n",
+            val);
+        return FALSE;
+    }
+    if( size <= sizeof( LOGFONT16)) {
+        LOGFONTA lfa;
+        LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
+        lfa.lfHeight = plf16->lfHeight;
+        lfa.lfWidth = plf16->lfWidth;
+        lfa.lfEscapement = plf16->lfEscapement;
+        lfa.lfOrientation = plf16->lfOrientation;
+        lfa.lfWeight = plf16->lfWeight;
+        lfa.lfItalic = plf16->lfItalic;
+        lfa.lfUnderline = plf16->lfUnderline;
+        lfa.lfStrikeOut = plf16->lfStrikeOut;
+        lfa.lfCharSet = plf16->lfCharSet;
+        lfa.lfOutPrecision = plf16->lfOutPrecision;
+        lfa.lfClipPrecision = plf16->lfClipPrecision;
+        lfa.lfQuality = plf16->lfQuality;
+        lfa.lfPitchAndFamily = plf16->lfPitchAndFamily;
+        memcpy( lfa.lfFaceName, plf16->lfFaceName, LF_FACESIZE );
+        if( lfa.lfHeight > 0) lfa.lfHeight = - MulDiv( lfa.lfHeight, dpi, 72);
+        hfont = CreateFontIndirectA( &lfa);
+    } else if( size <= sizeof( LOGFONTA)) {
+        LOGFONTA *plfa = (LOGFONTA*) &lfw;
+        if( plfa->lfHeight > 0) plfa->lfHeight = - MulDiv( plfa->lfHeight, dpi, 72);
+        hfont = CreateFontIndirectA( plfa);
+    } else {
+        if( lfw.lfHeight > 0) lfw.lfHeight = - MulDiv( lfw.lfHeight, dpi, 72);
+        hfont = CreateFontIndirectW( &lfw);
+    }
+    ok( hfont != NULL, "CreateFont (%s) failed, gle %ld\n", val, GetLastError());
+    if( !hfont) return FALSE;
+    hfont = SelectObject( hdc, hfont);
+    GetTextMetricsA( hdc, ptm);
+    if( avcw) {
+        /* calculate average character width */
+        GetTextExtentPoint( hdc, chrs, 52, &sz );
+        *avcw = (sz.cx + 26)/52;
+    }
+    hfont = SelectObject( hdc, hfont);
+    DeleteObject( hfont);
+    return TRUE;
+}
+
+int gsm_error_ctr;
+
+#define ok_gsm( i, v)\
+{\
+    int exp = (v);\
+    int act = GetSystemMetrics( (i));\
+    if( exp != act) gsm_error_ctr++;\
+    ok( exp==act,"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
+}
+
+void test_GetSystemMetrics( int multitest)
+{
+    HKEY hkey;
+    DWORD ret;
+    int dpi;
+    int CaptionFontOK;
+    TEXTMETRICA tmCaptionFont;
+    int MenuFontOK;
+    TEXTMETRICA tmMenuFont;
+    int SmCaptionFontOK;
+    TEXTMETRICA tmSmCaptionFont;
+    /* int IconFontOK;
+    TEXTMETRICA tmIconFont; */
+    /* int MessageFontOK;
+    TEXTMETRICA tmMessageFont; */
+    /*int StatusFontOK;
+    TEXTMETRICA tmStatusFont;*/
+    HDC hdc = CreateIC( "Display", 0, 0, 0);
+    INT BorderWidth,
+        CaptionWidth,
+        CaptionHeight,
+        IconSpacing,
+        IconVerticalSpacing,
+        /* IconTitleWrap, */
+        MenuHeight,
+        MenuWidth,
+        ScrollHeight,
+        ScrollWidth,
+        SmCaptionHeight,
+        SmCaptionWidth;
+    INT avcwCaption;
+
+    dpi = GetDeviceCaps( hdc, LOGPIXELSY);
+
+
+    ret= RegOpenKeyA( HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", &hkey );
+    if( ret != ERROR_SUCCESS) { /* happens on NT 3.51 */
+        trace("Reg Key HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics not available. GetSystemMetrics tests skipped.\n");
+        return;
+    }
+    /* get text metrics of those fonts */
+    CaptionFontOK = gsm_tmfromreg( hkey, hdc, "CaptionFont", &tmCaptionFont, &avcwCaption, dpi);
+    /* IconFontOK = gsm_tmfromreg( hkey, hdc, "IconFont", &tmIconFont, NULL, dpi); */
+    MenuFontOK = gsm_tmfromreg( hkey, hdc, "MenuFont", &tmMenuFont, NULL, dpi);
+    /* MessageFontOK = gsm_tmfromreg( hkey, hdc, "MessageFont", &tmMessageFont, NULL, dpi); */
+    SmCaptionFontOK = gsm_tmfromreg( hkey, hdc, "SmCaptionFont", &tmSmCaptionFont, NULL, dpi);
+    /* StatusFontOK = gsm_tmfromreg( hkey, hdc, "StatusFont", &tmStatusFont, NULL, dpi); */
+    /* get others */
+    BorderWidth=gsm_valfromreg(hkey,"BorderWidth", dpi);
+    CaptionWidth=gsm_valfromreg(hkey,"CaptionWidth", dpi);
+    CaptionHeight=gsm_valfromreg(hkey,"CaptionHeight", dpi);
+    IconSpacing=gsm_valfromreg(hkey,"IconSpacing", dpi);
+    IconVerticalSpacing=gsm_valfromreg(hkey,"IconVerticalSpacing", dpi);
+    /* IconTitleWrap=gsm_valfromreg(hkey,"IconTitleWrap", dpi); */
+    MenuHeight=gsm_valfromreg(hkey,"MenuHeight", dpi);
+    MenuWidth=gsm_valfromreg(hkey,"MenuWidth", dpi);
+    ScrollHeight=gsm_valfromreg(hkey,"ScrollHeight", dpi);
+    ScrollWidth=gsm_valfromreg(hkey,"ScrollWidth", dpi);
+    SmCaptionHeight=gsm_valfromreg(hkey,"SmCaptionHeight", dpi);
+    SmCaptionWidth=gsm_valfromreg(hkey,"SmCaptionWidth", dpi);
+
+    /* lo-limit some values as done in Windows */
+    if( CaptionWidth < 8) CaptionWidth = 8;
+    if( ScrollWidth < 8) ScrollWidth =8;
+    if( ScrollHeight < 8) ScrollHeight =8;
+    /* reset error counters */
+    gsm_error_ctr = 0;
+    /* the tests: */
+
+    /* SM_CXSCREEN, can not test these two */
+    /* SM_CYSCREEN */
+    ok_gsm( SM_CXVSCROLL,  ScrollWidth);
+    ok_gsm( SM_CXHSCROLL,  ScrollHeight);
+    ok_gsm( SM_CYCAPTION, max( tmCaptionFont.tmHeight + 3, CaptionHeight + 1));
+    if( CaptionHeight < 8) CaptionHeight = 8;
+    ok_gsm( SM_CXBORDER, 1);
+    ok_gsm( SM_CYBORDER, 1);
+    ok_gsm( SM_CXDLGFRAME, 3);
+    ok_gsm( SM_CYDLGFRAME, 3);
+    ok_gsm( SM_CYVTHUMB,  ScrollHeight);
+    ok_gsm( SM_CXHTHUMB,  ScrollHeight);
+    /* SM_CXICON */
+    /* SM_CYICON */
+    /* SM_CXCURSOR */
+    /* SM_CYCURSOR */
+    ok_gsm( SM_CYMENU, max( MenuHeight + 1,
+            tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading +3));
+    ok_gsm( SM_CXFULLSCREEN,
+            GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYFULLSCREEN,
+            GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
+    /* SM_CYKANJIWINDOW */
+    /* SM_MOUSEPRESENT */
+    ok_gsm( SM_CYVSCROLL, ScrollHeight);
+    ok_gsm( SM_CXHSCROLL, ScrollHeight);
+    /* SM_DEBUG */
+    /* SM_SWAPBUTTON */
+    /* SM_RESERVED1 */
+    /* SM_RESERVED2 */
+    /* SM_RESERVED3 */
+    /* SM_RESERVED4 */
+    ok_gsm( SM_CXMIN, 3 * CaptionWidth + GetSystemMetrics( SM_CYSIZE) + 4 +
+        4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
+        2 * GetSystemMetrics( SM_CYFRAME));
+    if( !multitest) {/* seems to be cached in XP */
+        if( GetSystemMetrics( SM_CXSIZE) == GetSystemMetrics( SM_CYCAPTION) - 1) {
+            ok_gsm( SM_CXSIZE, GetSystemMetrics( SM_CYCAPTION) - 1); /* WinXP style */
+        } else {
+            ok_gsm( SM_CXSIZE, CaptionWidth); /* classic/standard windows style */
+        }
+    }
+    ok_gsm( SM_CYSIZE,  GetSystemMetrics( SM_CYCAPTION) - 1);
+    ok_gsm( SM_CXFRAME, max( BorderWidth + 3, 4));
+    ok_gsm( SM_CYFRAME, max( BorderWidth + 3, 4));
+    ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
+    ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
+    /* SM_CXDOUBLECLK */
+    /* SM_CYDOUBLECLK */
+    if( IconSpacing >= 0)
+        ok_gsm( SM_CXICONSPACING, IconSpacing);
+    if( IconVerticalSpacing >= 0)
+        ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
+    /* SM_MENUDROPALIGNMENT */
+    /* SM_PENWINDOWS */
+    /* SM_DBCSENABLED */
+    /* SM_CMOUSEBUTTONS */
+    /* SM_SECURE */
+    ok_gsm( SM_CXEDGE, 2);
+    ok_gsm( SM_CYEDGE, 2);
+    ok_gsm( SM_CXMINSPACING, 160);
+    /* SM_CYMINSPACING */
+    /* SM_CXSMICON */
+    /* SM_CYSMICON */
+    ok_gsm( SM_CYSMCAPTION, max( tmSmCaptionFont.tmHeight + 3, SmCaptionHeight + 1));
+    if( !multitest) {/* seems to be cached in XP */
+        if( GetSystemMetrics( SM_CXSMSIZE) == GetSystemMetrics( SM_CYSMCAPTION) - 1) {
+            ok_gsm( SM_CXSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1); /* WinXP style */
+        } else {
+            ok_gsm( SM_CXSMSIZE, SmCaptionWidth); /* classic/standard windows style */
+        }
+    }
+    ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
+    if( MenuWidth <= 8 && 8 == GetSystemMetrics( SM_CXMENUSIZE)) {
+        ok_gsm( SM_CXMENUSIZE, 8);
+    } else {
+        ok_gsm( SM_CXMENUSIZE, MenuWidth);
+    }
+    ok_gsm( SM_CYMENUSIZE, GetSystemMetrics( SM_CYMENU) - 1);
+    /* SM_ARRANGE */
+    ok_gsm( SM_CXMINIMIZED, 160);
+    ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
+    ok_gsm( SM_CXMAXTRACK, GetSystemMetrics( SM_CXSCREEN) +
+        4 + 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYMAXTRACK, GetSystemMetrics( SM_CYSCREEN) +
+        4 + 2 * GetSystemMetrics( SM_CYFRAME));
+    /* the next two cannot really be tested as they depend on (application) toolbars */
+    /* SM_CXMAXIMIZED */
+    /* SM_CYMAXIMIZED */
+    /* SM_NETWORK */
+    /* */
+    /* */
+    /* */
+    /* SM_CLEANBOOT */
+    /* SM_CXDRAG */
+    /* SM_CYDRAG */
+    /* SM_SHOWSOUNDS */
+    ok_gsm( SM_CXMENUCHECK,
+            ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
+    ok_gsm( SM_CYMENUCHECK,
+            ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
+    /* SM_SLOWMACHINE */
+    /* SM_MIDEASTENABLED */
+    /* SM_MOUSEWHEELPRESENT */
+    /* SM_XVIRTUALSCREEN */
+    /* SM_YVIRTUALSCREEN */
+    /* SM_CXVIRTUALSCREEN */
+    /* SM_CYVIRTUALSCREEN */
+    /* SM_CMONITORS */
+    /* SM_SAMEDISPLAYFORMAT */
+    /* SM_IMMENABLED */
+    /* SM_CXFOCUSBORDER */
+    /* SM_CYFOCUSBORDER */
+    /* SM_TABLETPC */
+    /* SM_MEDIACENTER */
+    /* SM_CMETRICS */
+    /* end of tests */
+    if( gsm_error_ctr ) {
+        trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
+                BorderWidth, CaptionWidth, CaptionHeight, IconSpacing, IconVerticalSpacing);
+        trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
+                MenuHeight, MenuWidth, ScrollHeight, ScrollWidth, SmCaptionHeight, SmCaptionWidth);
+        trace( "CaptionFont %ld,%ld,%d  MenuFont %ld,%ld SmCaptionFont %ld,%ld\n",
+                tmCaptionFont.tmHeight, tmCaptionFont.tmExternalLeading, avcwCaption,
+                tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading,
+                tmSmCaptionFont.tmHeight, tmSmCaptionFont.tmExternalLeading);
+    }
+    ReleaseDC( 0, hdc);
+    RegCloseKey( hkey );
+}
+
+int getrandom( int lo, int hi)
+{
+    /* Get random number from specific range. see "man 3 rand" */
+    return lo + (int)((double) (hi-lo) * rand() / (RAND_MAX + 1.0));
+}
+
+/* do multiple GetSystemMetrics tests with random metrics */
+void multitest_gsm(int times)
+{
+    int i;
+    HDC hdc = GetDC(0);
+    int dpi;
+    int iswin9x = GetVersion() & 0x80000000;
+    NONCLIENTMETRICS ncm, ncmsav;
+    ICONMETRICS im, imsav;
+
+    dpi = GetDeviceCaps( hdc, LOGPIXELSY);
+    ReleaseDC( 0, hdc);
+    srand( GetTickCount());
+
+    ncm.cbSize = sizeof( ncm);
+    SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
+    ncmsav = ncm;
+    im.cbSize = sizeof( im);
+    SystemParametersInfo( SPI_GETICONMETRICS, 0, &im, 0);
+    imsav = im;
+    for( i=1;i<=times;i++) {
+        ncm.iBorderWidth = getrandom( 0, 20);
+        ncm.iCaptionHeight = getrandom( 0, 40);
+        ncm.iCaptionWidth = getrandom( 0,40);
+        ncm.iMenuHeight = getrandom( 0,40);
+        ncm.iMenuWidth = getrandom( 0,80);
+        ncm.iScrollHeight = getrandom( 0, 40);
+        ncm.iScrollWidth = getrandom( 0, 40);
+        ncm.iSmCaptionHeight = getrandom( 0, 40);
+        ncm.iSmCaptionWidth = getrandom( 0,40);
+        /* win9x stores font sizes as points (inch/72) in registry
+         * NT/2k/XP stores fontsize as logical pixels in the registry
+         * Because not every logical pixel size corresponds to a
+         * point size we must for win9x first generate a random point size
+         * and convert that to logical pixels.
+         */
+        ncm.lfCaptionFont.lfHeight = iswin9x ? - MulDiv( getrandom( 3, 40), dpi, 72)
+                                             : - getrandom( 2, 60);
+        ncm.lfMenuFont.lfHeight = iswin9x ? - MulDiv( getrandom( 3, 40), dpi, 72)
+                                             : - getrandom( 2, 60);
+        ncm.lfSmCaptionFont.lfHeight = iswin9x ? - MulDiv( getrandom( 3, 40), dpi, 72)
+                                             : - getrandom( 2, 60);
+        SystemParametersInfo( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
+            SPIF_SENDCHANGE);
+        im.iHorzSpacing = getrandom( 32, 200);
+        im.iVertSpacing = getrandom( 32, 200);
+        SystemParametersInfo( SPI_SETICONMETRICS, 0, &im, SPIF_UPDATEINIFILE|
+            SPIF_SENDCHANGE);
+        trace("GetSystemMetrics test run %d of %d\n", i, times);
+        test_GetSystemMetrics(TRUE);
+    }
+    SystemParametersInfo( SPI_SETNONCLIENTMETRICS, 0, &ncmsav, SPIF_UPDATEINIFILE|
+        SPIF_SENDCHANGE);
+    SystemParametersInfo( SPI_SETICONMETRICS, 0, &imsav, SPIF_UPDATEINIFILE|
+        SPIF_SENDCHANGE);
+}
+
 START_TEST(sysparams)
 {
     int argc;
@@ -1708,6 +2081,20 @@ START_TEST(sysparams)
     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
     trace("strict=%d\n",strict);
 
+    /* for the convenience of testing a <number> of random
+     * generated windows metrics on Windows add
+     * "multi <number>" as arguments. Otherwise only the current
+     * metrics is tested */
+    if( argc >= 3 && strcmp(argv[2],"multi")==0) {
+        int i;
+        if( argc < 4 || ( i= atoi(argv[3]))<= 0)
+            i=10;
+        multitest_gsm(i);
+    } else {
+        trace("testing GetSystemMetrics of current configuration\n");
+        test_GetSystemMetrics(FALSE);
+    }
+
     change_counter = 0;
     change_last_param = 0;
 


More information about the wine-patches mailing list