HMCL icon indicating copy to clipboard operation
HMCL copied to clipboard

[Feature] 添加截图功能

Open neveler opened this issue 1 month ago • 2 comments

概述 | Summary

用户按下 F2 后,使用当前时间等信息作为截图文件名称并保存在指定的截图目录下。

该功能使用频率可能不高因此可默认禁用,并在设置中启用后 F2 才生效。

原因 | Reason

使用第三方截图工具截取 HMCL 时,可能会出现截图尺寸比窗口略大,从而导致截图中包含额外的背景内容。

支持截图后,生成的图片可用于问题反馈及文档截图。

详情 | Description

添加全局 F2 监听事件,事件触发后获取所有 Window 对象,根据该对象获取其位置坐标及使用透明背景填充的截图,然后将所有截图根据位置关系合成为一张图片。

// press F2 to take a screenshot
navigator.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
    if (e.getCode() != KeyCode.F2) return;
    SnapshotParameters transparentParams = new SnapshotParameters();
    transparentParams.setFill(Color.TRANSPARENT);
    record Shot(BufferedImage img, double x, double y) {
    }

    List<Shot> shots = new ArrayList<>();
    for (Window window : Window.getWindows()) {
        if (!window.isShowing() || window.getScene() == null || window.getScene().getRoot() == null) continue;
        WritableImage snapshot = window.getScene().getRoot().snapshot(transparentParams, null);
        BufferedImage image = SwingFXUtils.fromFXImage(snapshot, null);
        if (image != null) {
            shots.add(new Shot(image, window.getX(), window.getY()));
        }
    }
    if (shots.isEmpty()) return;

    double minX = shots.stream().mapToDouble(shot -> shot.x).min().orElse(0);
    double minY = shots.stream().mapToDouble(shot -> shot.y).min().orElse(0);
    double maxX = shots.stream().mapToDouble(shot -> shot.x + shot.img.getWidth()).max().orElse(0);
    double maxY = shots.stream().mapToDouble(shot -> shot.y + shot.img.getHeight()).max().orElse(0);

    int width = (int)(maxX - minX);
    int height = (int)(maxY - minY);

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D graphics = image.createGraphics();
    shots.forEach(shot -> graphics.drawImage(shot.img, (int)(shot.x - minX), (int)(shot.y - minY), null));
    graphics.dispose();

    try {
        ImageIO.write(image, "png", new File("out.png"));
    } catch (IOException ignored) {
    }
});

截图效果

Image Image

neveler avatar Dec 05 '25 08:12 neveler

窗户边框是HMCL自行绘制的,对操作系统而言这一圈阴影就是窗口的内容,个人感觉没啥必要 在macOS弹出文件选择器的时候会给窗口加遮罩,也可以看出来这个问题

Image

WhatDamon avatar Dec 05 '25 09:12 WhatDamon

https://github.com/HMCL-dev/HMCL/issues/2081

zkitefly avatar Dec 05 '25 10:12 zkitefly