Windows scaling
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))
.