Skip to content

Instantly share code, notes, and snippets.

@jcoester
Last active February 17, 2024 20:39
Show Gist options
  • Save jcoester/52817d1fd7b8018e8127b57c56079804 to your computer and use it in GitHub Desktop.
Save jcoester/52817d1fd7b8018e8127b57c56079804 to your computer and use it in GitHub Desktop.
Java: Retrieve current Windows Display Scale during runtime, e.g. 1.0 = 100%, 1.25 = 125%, 1.5 = 150%, 1.75 = 175%, 2.0 = 200%
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.WinDef;
import java.awt.Toolkit;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* This <code>WindowsDisplayScale</code> class retrieves the current <code>Windows Display
* Scale</code> throughout a <code>Java</code> applications' runtime, e.g.
* <code>1.0 = 100%, 1.25 = 125%, 1.5 = 150%, 1.75 = 175%, 2.0 = 200%</code>.
*
* <p>It uses <code>Java AWT</code> and the <code>Java Native Access (JNA) platform</code>
* to access the <code>Display Device Context (DC)</code> from <code>Microsoft
* Windows graphics device interface (GDI)</code></p>
*
* @implNote Requires <code>net.java.dev.jna.platform (Maven)</code>
* <p>Full support for <code>Java 8</code> on <code>Windows 11</code>: Value updates throughout runtime</p>
* <p>Partial support for <code>Java 11</code> on <code>Windows 11</code>: Value from application startup</p>
*
* @author <a href="https://gist.github.com/jcoester/52817d1fd7b8018e8127b57c56079804">jcoester</a>
* @author built on previous version from <a href="https://gist.github.com/tresf/00a8ed7c9860e3bd73cebf764a49789f">tresf</a>
* @version 1.0 (2024 Feb. 17)
*/
public class WindowsDisplayScale {
public static void main(String[] args) {
// For demonstration: Check Windows Display Scale every 5 seconds
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(WindowsDisplayScale::update, 0, 5, TimeUnit.SECONDS);
}
private static void update() {
// Retrieval of the Windows Display Scale
double scaleDecimal = detectWindowsDisplayScale();
int scalePercentage = (int) (scaleDecimal * 100);
// Usage of the Windows Display Scale
System.out.println("Windows Display Scale (double): " + scaleDecimal); // e.g. 1.0, 1.25, 1.5, 1.75, 2.0
System.out.println("Windows Display Scale ( int% ): " + scalePercentage); // e.g. 100, 125, 150, 175, 200
System.out.println(); // Easier readability during demonstration
}
public static double detectWindowsDisplayScale() {
/* Retrieve AWT scale
* (Detects the Windows Display Scale once during application startup) */
double awtScale = Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f;
// Retrieve HDC (Handle to Device Context (DC))
WinDef.HDC hdc = GDI32.INSTANCE.CreateCompatibleDC(null);
if (hdc == null)
return 0;
/* Retrieve HDC Display info
* (Detects changes to the Windows Display Scale during the application runtime) */
double a = GDI32.INSTANCE.GetDeviceCaps(hdc, 10); // 10=VERTRES
double b = GDI32.INSTANCE.GetDeviceCaps(hdc, 117); // 117=DESKTOPVERTRES
GDI32.INSTANCE.DeleteDC(hdc);
if (a == 0 || b == 0)
return 0;
// Offset HDC Vertical pixels with the initial AWT scale
b = b * awtScale;
// Calculate Windows Display Scale
double windowsDisplayScale = a > b ? a / b : b / a;
// Round to two decimals and return
return BigDecimal.valueOf(windowsDisplayScale).setScale(2, RoundingMode.HALF_UP).doubleValue();
}
}
@jcoester
Copy link
Author

Windows Settings Java 8 output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment