Windows 8/10已经开始包含一个滑块,用于调整GUI元素的大小,右键单击桌面-〉显示屏。对于一个使用笔记本电脑4k屏幕的同事来说,它是250%,而另一个同事使用相同分辨率的4k 28”屏幕,它是150%。我如何以编程方式读取该值?我需要调整一些图形,使其在所有屏幕上看起来都一样。我正在用Java开发一个Eclipse RCP应用程序,但是通过JNI使用C或C++的方法也可以工作,我已经四处寻找了,但是没有找到任何东西。
vnjpjtjt1#
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()参见API以每英寸点数为单位返回屏幕分辨率。假设你的100%是96像素,你可以计算你的缩放因子。
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
8ljdwjyq2#
下面的工作对我来说。你需要得到窗口实际设备(多显示器环境)和计算它的约束尺寸和显示模式尺寸。
public static double getWindowScale(Window window) { GraphicsDevice device = getWindowDevice(window); return device.getDisplayMode().getWidth() / (double) device.getDefaultConfiguration().getBounds().width; } public static GraphicsDevice getWindowDevice(Window window) { Rectangle bounds = window.getBounds(); return asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()).stream() // pick devices where window located .filter(d -> d.getDefaultConfiguration().getBounds().intersects(bounds)) // sort by biggest intersection square .sorted((f, s) -> Long.compare(// square(f.getDefaultConfiguration().getBounds().intersection(bounds)), square(s.getDefaultConfiguration().getBounds().intersection(bounds)))) // use one with the biggest part of the window .reduce((f, s) -> s) // // fallback to default device .orElse(window.getGraphicsConfiguration().getDevice()); } public static long square(Rectangle rec) { return Math.abs(rec.width * rec.height); }
lnlaulya3#
也许here中的answer可以帮助您:
[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% }
gojuced74#
虽然问题询问的是Windows伸缩,但可接受的解决方案不能与运行JDK11的Linux正常工作。下面的技术使用JNA来检测Linux上的屏幕比例因子,这与公开Gtk(Gimp Toolkit)库的Linux桌面兼容。此代码片段包含几个Gtk版本相关的解决方案,因为Gtk API显示的缩放信息已经更改了几次。此外,由于缩放是特定于显示器的,因此对于特定用例(在同一桌面上混合使用标准和HiDPI显示器),信息可能不准确。
用法:GtkUtilities.getScaleFactor()
GtkUtilities.getScaleFactor()
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import java.lang.reflect.Method; public class GtkUtilities { /** * Initializes Gtk2/3 and returns the desktop scaling factor, usually 1.0 or 2.0 */ public static double getScaleFactor() { GTK gtkHandle = getGtkInstance(); if (gtkHandle != null && gtkHandle.gtk_init_check(0, null)) { System.out.println("Initialized Gtk"); if (gtkHandle instanceof GTK2) { return getGtk2ScaleFactor((GTK2)gtkHandle); } else { return getGtk3ScaleFactor((GTK3)gtkHandle); } } else { System.err.println("An error occurred initializing the Gtk library"); } return 0; } private static GTK getGtkInstance() { System.out.println("Finding preferred Gtk version..."); switch(getGtkMajorVersion()) { case 2: return GTK2.INSTANCE; case 3: return GTK3.INSTANCE; default: System.err.println("Not a compatible Gtk version"); } return null; } /** * Get the major version of Gtk (e.g. 2, 3) * UNIXToolkit is unavailable on Windows or Mac; reflection is required. * @return Major version if found, zero if not. */ private static int getGtkMajorVersion() { try { Class toolkitClass = Class.forName("sun.awt.UNIXToolkit"); Method versionMethod = toolkitClass.getDeclaredMethod("getGtkVersion"); Enum versionInfo = (Enum)versionMethod.invoke(toolkitClass); Method numberMethod = versionInfo.getClass().getDeclaredMethod("getNumber"); int version = ((Integer)numberMethod.invoke(versionInfo)).intValue(); System.out.println("Found Gtk " + version); return version; } catch(Throwable t) { System.err.println("Could not obtain GtkVersion information from UNIXToolkit: {}", t.getMessage()); } return 0; } private static double getGtk2ScaleFactor(GTK2 gtk2) { Pointer display = gtk2.gdk_display_get_default(); System.out.println("Gtk 2.10+ detected, calling \"gdk_screen_get_resolution\""); Pointer screen = gtk2.gdk_display_get_default_screen(display); return gtk2.gdk_screen_get_resolution(screen) / 96.0d; } private static double getGtk3ScaleFactor(GTK3 gtk3) { Pointer display = gtk3.gdk_display_get_default(); int gtkMinorVersion = gtk3.gtk_get_minor_version(); if (gtkMinorVersion < 10) { System.err.println("Gtk 3.10+ is required to detect scaling factor, skipping."); } else if (gtkMinorVersion >= 22) { System.out.println("Gtk 3.22+ detected, calling \"gdk_monitor_get_scale_factor\""); Pointer monitor = gtk3.gdk_display_get_primary_monitor(display); return gtk3.gdk_monitor_get_scale_factor(monitor); } else if (gtkMinorVersion >= 10) { System.out.println("Gtk 3.10+ detected, calling \"gdk_screen_get_monitor_scale_factor\""); Pointer screen = gtk3.gdk_display_get_default_screen(display); return gtk3.gdk_screen_get_monitor_scale_factor(screen, 0); } return 0; } /** * Gtk2/Gtk3 wrapper */ private interface GTK extends Library { // Gtk2.0+ boolean gtk_init_check(int argc, String[] argv); Pointer gdk_display_get_default(); Pointer gdk_display_get_default_screen (Pointer display); } private interface GTK3 extends GTK { GTK3 INSTANCE = Native.loadLibrary("gtk-3", GTK3.class); // Gtk 3.0+ int gtk_get_minor_version (); // Gtk 3.10-3.21 int gdk_screen_get_monitor_scale_factor (Pointer screen, int monitor_num); // Gtk 3.22+ Pointer gdk_display_get_primary_monitor (Pointer display); int gdk_monitor_get_scale_factor (Pointer monitor); } private interface GTK2 extends GTK { GTK2 INSTANCE = Native.loadLibrary("gtk-x11-2.0", GTK2.class); // Gtk 2.1-3.0 double gdk_screen_get_resolution(Pointer screen); } }
a64a0gku5#
采用@seth-kitchen使用JNA的示例,这是可能的,即使在较老的JDK(如Java8)上也是如此。
**注意:**此技术的JNA部分在JDK 11上不能很好地工作。代码中的注解解释了它将如何回退到Toolkit技术。
Toolkit
public static double 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 (double)logical/actual; } } return Toolkit.getDefaultToolkit().getScreenResolution() / 96.0d; }
上面的解决方案为了简单起见获取了默认显示。您可以通过查找当前窗口句柄(通过Native.getComponentPointer(Component)或使用User32.INSTANCE.FindWindow(...)按标题)然后使用CreateaCompatibleDC(GetDC(window))来增强它以获得当前窗口的显示。
Native.getComponentPointer(Component)
User32.INSTANCE.FindWindow(...)
CreateaCompatibleDC(GetDC(window))
1wnzp6jl6#
此功能适用于macOS和Windows以及Java 17
public static Window getWindow(Component component) { return component instanceof Window ? (Window) component : getWindow(component.getParent()); } @Override public synchronized void paintComponent(Graphics g) { super.paintComponent(g); float displayScaling = (float) getWindow(this).getGraphicsConfiguration().getDefaultTransform().getScaleX(); }
tjrkku2a7#
下面是一个“一行程序”,它应该可以为您提供比例因子:
double scale = java.awt.GraphicsEnvironment .getLocalGraphicsEnvironment() .getDefaultScreenDevice() // or cycle your getScreenDevices() .getDefaultConfiguration() .getDefaultTransform() .getScaleX();
如果您已经有一个java.awt.组件,您可以使用以下代码:
double scale = myComponent.getGraphicsConfiguration().getDefaultTransform().getScaleX();
(基于本文)
7条答案
按热度按时间vnjpjtjt1#
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
参见API以每英寸点数为单位返回屏幕分辨率。
假设你的100%是96像素,你可以计算你的缩放因子。
8ljdwjyq2#
下面的工作对我来说。你需要得到窗口实际设备(多显示器环境)和计算它的约束尺寸和显示模式尺寸。
lnlaulya3#
也许here中的answer可以帮助您:
gojuced74#
虽然问题询问的是Windows伸缩,但可接受的解决方案不能与运行JDK11的Linux正常工作。
下面的技术使用JNA来检测Linux上的屏幕比例因子,这与公开Gtk(Gimp Toolkit)库的Linux桌面兼容。
此代码片段包含几个Gtk版本相关的解决方案,因为Gtk API显示的缩放信息已经更改了几次。此外,由于缩放是特定于显示器的,因此对于特定用例(在同一桌面上混合使用标准和HiDPI显示器),信息可能不准确。
用法:
GtkUtilities.getScaleFactor()
a64a0gku5#
采用@seth-kitchen使用JNA的示例,这是可能的,即使在较老的JDK(如Java8)上也是如此。
**注意:**此技术的JNA部分在JDK 11上不能很好地工作。代码中的注解解释了它将如何回退到
Toolkit
技术。上面的解决方案为了简单起见获取了默认显示。您可以通过查找当前窗口句柄(通过
Native.getComponentPointer(Component)
或使用User32.INSTANCE.FindWindow(...)
按标题)然后使用CreateaCompatibleDC(GetDC(window))
来增强它以获得当前窗口的显示。1wnzp6jl6#
此功能适用于macOS和Windows以及Java 17
tjrkku2a7#
下面是一个“一行程序”,它应该可以为您提供比例因子:
如果您已经有一个java.awt.组件,您可以使用以下代码:
(基于本文)