You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中截取非活跃状态下的指定软件窗口截图?

实现非活跃指定窗口的定时截图

要截取非活跃状态的指定窗口,Java标准库的Robot类无法直接获取目标窗口的位置和句柄,需要借助**JNA(Java Native Access)**调用Windows系统API来实现。以下是完整的实现步骤和代码:

1. 引入JNA依赖

如果使用Maven,在pom.xml中添加:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>

2. 核心实现代码

步骤说明:

  • 通过窗口标题找到目标窗口的句柄(HWND)
  • 获取窗口的屏幕坐标和尺寸
  • 用Robot截取对应区域,或调用系统API直接截图(更稳定)
  • 定时执行截图任务
import com.sun.jna.Native;
import com.sun.jna.platform.win32.*;
import com.sun.jna.win32.W32APIOptions;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

// 定义JNA接口,调用Windows API
interface User32 extends StdCallLibrary {
    User32 INSTANCE = Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
    HWND FindWindow(String lpClassName, String lpWindowName);
    boolean GetWindowRect(HWND hWnd, WinUser.RECT rect);
}

interface GDI32 extends StdCallLibrary {
    GDI32 INSTANCE = Native.load("gdi32", GDI32.class);
    HDC GetDC(HWND hWnd);
    HDC CreateCompatibleDC(HDC hdc);
    HBITMAP CreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight);
    HBITMAP SelectObject(HDC hdc, HBITMAP hBitmap);
    boolean BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, int dwRop);
    boolean DeleteObject(HBITMAP hBitmap);
    int ReleaseDC(HWND hWnd, HDC hdc);
    boolean DeleteDC(HDC hdc);
}

public class WindowCapture {
    // 目标窗口标题(替换成你要截图的窗口标题)
    private static final String TARGET_WINDOW_TITLE = "记事本";
    // 截图保存路径
    private static final String SAVE_PATH = "C:\\Users\\Public\\Documents\\tessdata\\window_capture_";
    // 定时间隔(单位:秒)
    private static final long INTERVAL = 10;

    public static void main(String[] args) {
        // 启动定时任务
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(WindowCapture::captureTargetWindow, 0, INTERVAL, TimeUnit.SECONDS);
    }

    private static void captureTargetWindow() {
        // 1. 找到目标窗口句柄
        HWND hwnd = User32.INSTANCE.FindWindow(null, TARGET_WINDOW_TITLE);
        if (hwnd == null || hwnd.equals(WinDef.NULL)) {
            System.err.println("未找到目标窗口:" + TARGET_WINDOW_TITLE);
            return;
        }

        // 2. 获取窗口的屏幕坐标和尺寸
        WinUser.RECT rect = new WinUser.RECT();
        if (!User32.INSTANCE.GetWindowRect(hwnd, rect)) {
            System.err.println("获取窗口位置失败");
            return;
        }
        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;

        // 方法一:用Robot截取指定区域(简单,但窗口被遮挡时会截取到遮挡内容)
        try {
            Robot robot = new Robot();
            BufferedImage image = robot.createScreenCapture(new Rectangle(rect.left, rect.top, width, height));
            String fileName = SAVE_PATH + System.currentTimeMillis() + ".png";
            ImageIO.write(image, "png", new File(fileName));
            System.out.println("截图保存成功:" + fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 方法二:调用Windows API直接截取窗口(即使被遮挡也能截到窗口内容,更稳定)
        // 注释掉方法一,取消注释以下代码即可使用
        /*
        HDC hdcSrc = GDI32.INSTANCE.GetDC(hwnd);
        HDC hdcDest = GDI32.INSTANCE.CreateCompatibleDC(hdcSrc);
        HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcSrc, width, height);
        HBITMAP hOldBitmap = GDI32.INSTANCE.SelectObject(hdcDest, hBitmap);

        // 复制窗口图像到兼容DC
        GDI32.INSTANCE.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, WinGDIOptions.SRCCOPY);

        // 将HBITMAP转换为BufferedImage
        BufferedImage image = WinGDI.HBITMAPToBufferedImage(hBitmap);

        // 释放资源
        GDI32.INSTANCE.SelectObject(hdcDest, hOldBitmap);
        GDI32.INSTANCE.DeleteObject(hBitmap);
        GDI32.INSTANCE.DeleteDC(hdcDest);
        GDI32.INSTANCE.ReleaseDC(hwnd, hdcSrc);

        try {
            String fileName = SAVE_PATH + System.currentTimeMillis() + ".png";
            ImageIO.write(image, "png", new File(fileName));
            System.out.println("截图保存成功:" + fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        */
    }
}

注意事项

  • 替换TARGET_WINDOW_TITLE为你要截图的窗口的准确标题(可以用Spy++工具查看窗口标题)
  • 方法一简单易实现,但如果窗口被其他窗口遮挡,会截取到遮挡的内容;方法二直接从窗口的DC获取图像,即使窗口被遮挡或最小化(需先恢复窗口)也能截取到窗口内容
  • 确保程序有文件写入权限,保存路径存在
  • 如果是最小化的窗口,需要先调用User32.INSTANCE.ShowWindow(hwnd, WinUser.SW_RESTORE)恢复窗口再截图

内容的提问来源于stack exchange,提问作者Hussin Tsouli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:20:25