Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows scaling

Tags:

java

c++

windows

Windows 8/10 has started to include a slider for how much GUI elements should scale, right click on desktop -> display. For a colleague with a laptop 4k-screen it's 250% while another colleague using the same resolution on a 4k 28" screen it's 150%.

How do I read that value programmatically? I need to adjust some graphics so it looks the same on all screens.

I'm working in Java on a Eclipse RCP application, but a way that uses C or C++ through JNI works too. I've been looking around but can't find anything.

like image 778
dutt Avatar asked Sep 15 '15 13:09

dutt


3 Answers

java.awt.Toolkit.getDefaultToolkit().getScreenResolution() see API

Returns the screen resolution in dots-per-inch.

Assumen your 100% is 96pixel you're able to calculate your scaling factor.

like image 149
Christian Avatar answered Sep 23 '22 10:09

Christian


Maybe this answer from here might help you:

[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
    VERTRES = 10,
    DESKTOPVERTRES = 117,

    // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
}  


private float getScalingFactor()
{
    Graphics g = Graphics.FromHwnd(IntPtr.Zero);
    IntPtr desktop = g.GetHdc();
    int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
    int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); 

    float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;

    return ScreenScalingFactor; // 1.25 = 125%
}
like image 31
Seth Kitchen Avatar answered Sep 24 '22 10:09

Seth Kitchen


Adopting @seth-kitchen's example using JNA, this is possible, even on older JDKs like Java 8.

Note: The JNA portion of this technique doesn't work well on JDK11. A comment in the code explains how it will fallback to the Toolkit technique.

public static int getScaleFactor() {
    WinDef.HDC hdc = GDI32.INSTANCE.CreateCompatibleDC(null);
    if (hdc != null) {
        int actual = GDI32.INSTANCE.GetDeviceCaps(hdc, 10 /* VERTRES */);
        int logical = GDI32.INSTANCE.GetDeviceCaps(hdc, 117 /* DESKTOPVERTRES */);
        GDI32.INSTANCE.DeleteDC(hdc);
        // JDK11 seems to always return 1, use fallback below
        if (logical != 0 && logical/actual > 1) {
            return logical/actual;
        }
    }
    return (int)(Toolkit.getDefaultToolkit().getScreenResolution() / 96.0);
}

This above solution grabs the default display for simplicity purposes. You can enhance it to get the display of the current Window by finding the current Window handle (through Native.getComponentPointer(Component) or by title using User32.INSTANCE.FindWindow(...)) and then using CreateaCompatibleDC(GetDC(window)).

like image 37
tresf Avatar answered Sep 22 '22 10:09

tresf