这个问题大家可能不陌生,一搜索,就一堆答案,大多是一行代码搞定
Toolkit.getDefaultToolkit().getScreenSize();
然而简单做了一个测试,效果如下,输出1707x960,而我电脑的分辨率是3840x2160,根本就不对
错误原因
Toolkit.getDefaultToolkit().getScreenSize()这种方式取得的屏幕尺寸没有考虑缩放问题,如果windows设置缩放不是100%,那么上述方法将取不到正确的之后,如下图,缩放设置的是225%,而1707x960和电脑的真实分辨率3840x2160正好差了225%倍
异常原因
由于windows设置了缩放比例,Toolkit.getDefaultToolkit().getScreenSize()并不能拿到真实的分辨率,拿到的屏幕的分辨率与真实分辨率正好差了缩放比例的倍数,可是这个缩放比例又没有接口可以弄到,这个是非常特殊的API,估计只有掉windows api,才能拿到这个参数,这个缩放比例无法通过正常途径获取,那么我们无法将Toolkit.getDefaultToolkit().getScreenSize();的分辨率换算成真实分辨率,也就是说Toolkit这种方法获取分辨率根本不可行,只能另寻出路
解决方案
本人查阅了大量的国内外论坛,至今没有发现这个问题的解决方案,国外有好多老外也有此问题,然而至今没有解决
本人反复调研,偶然间发现了一个屏幕截图的接口
BufferedImage bi = (new Robot()).createScreenCapture(new Rectangle(x, y, width, height));
这行代码,可以实现将屏幕上一个区域截取成一个图片,经过测试,这个图片和屏幕的分辨率是匹配的,因此我们可以利用这个接口,拿到屏幕的分辨率,具体原理如下:
以(0,0)为起点截取一个足够大的图片,当这个图片足够大(超出屏幕大小时)时,这个图片的右侧和下侧会超出屏幕的尺寸,那么截取来的图片右侧和下侧,会有一条黑色的边缘,因此我们用截取图片的大小减去右侧和下侧边缘的尺寸,就是屏幕的大小
实现源码如下:
package test;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
public class TestScreenSize {
public static BufferedImage getScreenImage(int x, int y, int width, int height) {
try {
return (new Robot()).createScreenCapture(new Rectangle(x, y, width, height));
} catch (Exception e) {
return null;
}
}
public static Dimension getScreenSize() {
return getScreenSizeFromImage(getScreenImage(0, 0, 10000, 5000));
}
private static Dimension getScreenSizeFromImage(BufferedImage image) {
if (image == null) {
return Toolkit.getDefaultToolkit().getScreenSize();
}
int width = image.getWidth();
int height = image.getHeight();
long[] w = new long[width];
long[] h = new long[height];
for (int i = 0; i < width; i++) {
long value = 0;
for (int j = 0; j < height; j++) {
value += image.getRGB(i, j);
}
w[i] = value;
}
for (int i = 0; i < height; i++) {
long value = 0;
for (int j = 0; j < width; j++) {
value += image.getRGB(j, i);
}
h[i] = value;
}
return new Dimension(getValidSize(w), getValidSize(h));
}
private static int getValidSize(long[] v) {
if (v == null || v.length == 0) {
return 0;
}
long last = v[v.length - 1];
for (int i = v.length - 1; i >= 0; i--) {
if (last != v[i]) {
return i + 1;
}
}
return 0;
}
public static void main(String[] args) {
System.out.println(getScreenSize());
}
}
经过测试效果如下:
可见,此时,我们拿到了真实的分辨率