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.
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.
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%
}
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))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With