none
GetSystemMetrics(SM_CXSIZE) liefert in Windows 10 falsche Ergebnisse. RRS feed

  • Frage

  • Hallo,

    Ich habe seit mehreren Jahren eine MFC-Anwendung, die einen Dialog links vom Minimize-Button positioniert.

    Die Berechnung für die Position:

    int size = GetSystemmetrics(SM_CXSIZE) * 3 + GetSystemMetrics(SM_CXEDGE) * 2 + GetSystemMetrics(SM_CXSIZEFRAME);

    Bisher hat diese Berechnung funktioniert. Mit Windows 10 überdeckt der Dialog allerdings den Minimize-Button um 50 Prozent. Was ist bei meiner Berechnung falsch oder hat hier Windows 10 ein Problem?

    Hardy Braunsdorf


    Dienstag, 18. Juni 2019 08:47

Antworten

  • Hallo,

    Für alle, die auch nach einer Lösung suchen:

    Ich habe jetzt festgestellt, das die Buttons und auch das Icon 28% größer sind, als bei GetSystemMetrics angegeben. Ich ändere die Größe einfach entsprechend und damit ist das Layout ordentlich. 

    Gruß

    Hardy

    Dienstag, 25. Juni 2019 11:58

Alle Antworten

  • Die Berechnung für die Position:

    int size = GetSystemmetrics(SM_CXSIZE) * 3 + GetSystemMetrics(SM_CXEDGE) * 2 + GetSystemMetrics(SM_CXSIZEFRAME);


    Hallo,

    das sieht eher nach einer Berechnung der "Breite" der drei Fensterbuttons aus, nicht nach einer Berechnung der "Position" (der Variablenname "size" verrät dies eigentlich auch). Wo fängt dein Dialog in der Captionbar an und wie breit ist er? Bitte zeige den Code.

    Gruß Guido

    BTW. Anstatt deinen Code nochmal einzutippen, solltest du ihn in deine Frage mit Copy-Paste reinkopieren. Denn dein Code birgt Compiler-Fehler: GetSystemmetrics.

    Dienstag, 18. Juni 2019 09:49
  • Hallo,

    der Quellcode ist Bestandteil eines großen Projektes und nicht so einfach zu kopieren.

    Hier ein Auszug.

    rectMain enthält die Koordinaten der Anwendung, rectStatus die Koordinaten des Dialoges.

    s_hDlgStatus enthält das Handle des Dialoges.

        CSize szEdge = 0, szSize = 0, szSizeFrame = 0, szOffset = 0;
        szEdge.cx = GetSystemMetrics(SM_CXEDGE);            //  Randgröße der Systembuttons
        szEdge.cy = GetSystemMetrics(SM_CYEDGE);

        szSize.cx = GetSystemMetrics(SM_CXSIZE);            //  Größe der Systembuttons
        szSize.cy = GetSystemMetrics(SM_CYSIZE);

        szSizeFrame.cx = GetSystemMetrics(SM_CXSIZEFRAME);  //  bei Fenster mit veränderbaren Fenstergröße
        szSizeFrame.cy = GetSystemMetrics(SM_CYSIZEFRAME);
        szSizeFrame.cx += (10 - szSizeFrame.cx);
        szOffset.cx = szSizeFrame.cx + (szSize.cx*3) - (szEdge.cx*2); // 3 Buttons und 2 Ränder
        szOffset.cy = szSizeFrame.cy + szEdge.cy;                     

        SetWindowPos( s_hDlgStatus, NULL,
                      rectMain.right - ( rectStatus.right - rectStatus.left ) - szOffset.cx,
                      rectMain.top + szOffset.cy,
                      0, 0, SWP_NOSIZE );

    GetSystemMetrics(SM_CXSIZE) liefert 36 

    GetSystemMetrics(SM_CXSIZEFRAME) liefert 4

    GetSystemMetrics(SM_CXEDGE) liefert 2

    Gruß Hardy

    Dienstag, 18. Juni 2019 10:13
  • Ja,

    ein Screenshot bei mir zeigt, dass ein Button so um die 44 Pixel breit ist, nicht 36. Bei einer Suche wegen SM_CXSIZE sieht man, dass es anscheinend ein bekanntes Problem ist, dass GetSystemMetrics(SM_CXSIZE) häufig einen falschen Wert zurückliefert.

    Verwende stattdessen besser WM_GETTITLEBARINFOEX: https://docs.microsoft.com/en-us/windows/desktop/menurc/wm-gettitlebarinfoex

    Gruß Guido


    Edit: https://stackoverflow.com/questions/33813965/how-can-i-measure-the-width-of-the-caption-bar-available-for-text
    Dienstag, 18. Juni 2019 10:45
  • WM_GETTITLEBARINFOEX

    Und hier ist die Routine, wie du an die Struktur rankommst: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-gettitlebarinfo

    Gruß Guido

    Dienstag, 18. Juni 2019 10:57
  • Hallo,

    danke für die Antwort.

    Das Ergebnis stimmt allerdings auch nicht. Mir wird hier 24 für alle 3 Buttons berechnet.

    TITLEBARINFOEX tiex;
    tiex.cbSize = sizeof( tiex );
    SendMessage( WM_GETTITLEBARINFOEX, 0, (LPARAM)&tiex ); 

    int width = tiex.rgrect[ 2 ].right - tiex.rgrect[ 2 ].left.

    widht ergibt 24.

    Gruß Hardy


    Dienstag, 18. Juni 2019 11:16
  • Hallo,

    danke für die Antwort.

    Das Ergebnis stimmt allerdings auch nicht. Mir wird hier 24 für alle 3 Buttons berechnet.

    TITLEBARINFOEX tiex;
    tiex.cbSize = sizeof( tiex );
    SendMessage( WM_GETTITLEBARINFOEX, 0, (LPARAM)&tiex ); 

    int width = tiex.rgrect[ 2 ].right - tiex.rgrect[ 2 ].left.

    widht ergibt 24.

    Gruß Hardy


    24 ist nicht für alle 3 Buttons, sondern nur für den Minimize Button.

    Versuch mal:

    int width = tiex.rgrect[ 5 ].right - tiex.rgrect[ 2 ].left.
    Aber am besten wäre es wohl, die Position zu bestimmen, indem du den Minimize-Button nimmst, ScreenToClient machst und dann die Breite deines Dialogs von rect.left abziehst. Dann brauchst du nicht die Breite der drei Buttons berechnen.

    Gruß Guido


    Dienstag, 18. Juni 2019 12:19
  • Hallo,

    ich erhalte für alle 3 Buttons den Wert 24.

    Auch die Position zu verwenden hatte keinen Erfolg. Vermutlich ist das ein Bug bei Windows 10. Ich werde wohl nicht drum herum kommen, die Werte für Windows 10 hart zu coden.

    Danke für deine Bemühungen.

    Gruß Hardy

    Dienstag, 18. Juni 2019 13:09
  • Hi,

    kann das Problem "DPI Awareness" heißen? Ich bin mir beinahe sicher, dass Deine Anwendung nicht dahingehend manifestiert ist. Was passiert denn mit Deinen harten Werten, wenn Du die Skalierung änderst? Passt es dann noch immer, oder gibt es dann wieder Probleme?

    Donnerstag, 20. Juni 2019 08:11
  • Hallo,

    nein das war es auch nicht.

    Ich habe im Manifest "dpiAware" auf true gesetzt.

    unsigned int dpix = 0, dpiy = 0;
    GetDpiForMonitor( MonitorFromWindow( m_hWnd, MONITOR_DEFAULTTONEAREST ), MDT_EFFECTIVE_DPI, &dpix, &dpiy );

    unsigned cxsize = GetSystemMetrics(SM_CXSIZE)

    Bei Einstellung 100% ist dpix und dpiy = 96 und cxsize = 36.

    Bei Einstellung 120% ist dpix und dpiy = 120 und cxsize = 46.

    Bei 100% ist der Button ca. 46 und bei 125% ca. 56 Pixel breit.

    Gruß Hardy

    Donnerstag, 20. Juni 2019 09:33
  • Hallo,

    Für alle, die auch nach einer Lösung suchen:

    Ich habe jetzt festgestellt, das die Buttons und auch das Icon 28% größer sind, als bei GetSystemMetrics angegeben. Ich ändere die Größe einfach entsprechend und damit ist das Layout ordentlich. 

    Gruß

    Hardy

    Dienstag, 25. Juni 2019 11:58