How to take screenshot of any java native application without bringing it to foreground in Java?

282 views Asked by At

I want to take the screenshot of a java native application ( any framework AWT, Swing, JavaFx ) without bringing it to the foreground. Are there any framework-specific methods available for this?

I have tried using Robot class to get the screenshot

private static void capture(int x, int y , int width , int height, String setName) {
    Robot robot = new Robot();
    Rectangle area = new Rectangle(x, y, width, height);
    BufferedImage image = robot.createScreenCapture(area);
    ImageIO.write(image, "png", new File(System.getProperty("user.dir") + "\\images\\" + setName +".png"));
}

Now robot class with just take the area coordinates and capture the image, whether the target application is on the top or not, to get the application on the top I am using JNA to bring it to focus

private static void bringToFocus() {
    for (DesktopWindow desktopWindow : WindowUtils.getAllWindows(true)) {
        if (desktopWindow.getTitle().contains("notepad")) {
            HWND hwnd = User32.INSTANCE.FindWindow(null, desktopWindow.getTitle());
            User32.INSTANCE.SetForegroundWindow(hwnd);
            break;
        }
    }
}

But this is an example where we need to capture only one application, if we need to capture 10 applications screenshots we need to one by one bring them to the front and capture and bring next.

Is there any framework specific method availabe which can take the application screenshot without bringing it to the front.

1

There are 1 answers

9
ControlAltDel On

If your screen shot only needs to be of the Java GUI, you can paint to a BufferedImage

public static Image screenShot(Component c) {
  BufferedImage im = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
  Graphics g = im.getGraphics();
  c.paint(g); // Paint is the proper entry point to painting a (J)Component, rather than paintComponent
  g.dispose(); // You should dispose of your graphics object after you've finished
  return im;
}

If your requirement is to paint the Java GUI component along with the rest of the screen, but like your java (J)Frame is in front, you can do that by painting the screen using the robot first, then doing what I've posted above, but with the BufferedImage (which has already been drawn on) being passed in as a parameter rather than being created in the method.