0

Need to make screenshot of some games. Found this JNA code, but when I try to do screen`s I just get black screen. When I try to do screen of some program, like WordPad ot smth it works well. As well I am bad in JNA, I want ask you about help. Is it possible to accomplish this task ?

public class Paint extends JFrame {
public BufferedImage capture(HWND hWnd) throws IOException {
    String gettime = Gettime.screentime();
    HDC hdcWindow = User32.INSTANCE.GetDC(hWnd);
    HDC hdcMemDC = GDI32.INSTANCE.CreateCompatibleDC(hdcWindow);
    RECT bounds = new RECT();
    User32Extra.INSTANCE.GetClientRect(hWnd, bounds);
    int width = bounds.right - bounds.left;
    int height = bounds.bottom - bounds.top;

    HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcWindow, width, height);
    HANDLE hOld = GDI32.INSTANCE.SelectObject(hdcMemDC, hBitmap);
    GDI32Extra.INSTANCE.BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, 0, 0, WinGDIExtra.SRCCOPY);
    GDI32.INSTANCE.SelectObject(hdcMemDC, hOld);
    GDI32.INSTANCE.DeleteDC(hdcMemDC);
    BITMAPINFO bmi = new BITMAPINFO();
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
    Memory buffer = new Memory(width * height * 4);
    GDI32.INSTANCE.GetDIBits(hdcWindow, hBitmap, 0, height, buffer, bmi, WinGDI.DIB_RGB_COLORS);

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    image.setRGB(0, 0, width, height, buffer.getIntArray(0, width * height), 0, width);
    GDI32.INSTANCE.DeleteObject(hBitmap);
    User32.INSTANCE.ReleaseDC(hWnd, hdcWindow);
    File outputfile = new File("C:\\image" +gettime+ ".jpg");
    ImageIO.write(image, "jpg", outputfile);
    return image;
}

public static void main(String[] args) throws IOException {

        new Paint();

}
BufferedImage image;

public Paint() throws IOException {
    HWND hWnd = User32.INSTANCE.FindWindow(null, "some game");
    this.image = capture(hWnd);

    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pack();
    setExtendedState(MAXIMIZED_BOTH);
    setVisible(true);
}
@Override
public void paint(Graphics g) {
    super.paint(g);
    g.drawImage(image, 20, 40, null);
}
}
Drop
  • 143
  • 1
  • 6
  • A fullscreen DirectX/OpenGL game communicates directly with your GPU's driver. Unless you're running in windowed mode, the game does not render the frames on a Windows `Window`. You'll need to hook into the game itself to get a screenshot via DirectX (or OpenGL): https://stackoverflow.com/q/1962142/996081 – cbr Sep 27 '17 at 19:54

2 Answers2

0

GDI32Util.getScreenshot(HWND hwnd)

Method is already provided in jna.

but my case is as the same as you.... the game screen is black... nothing...

123
  • 1
  • 1
-1

Using JNA to take a screenshot sounds utterly complicated, besides not being platform-agnostic. Java has built-in functionality to take screenshots using the Robot class:

import java.awt.Robot;

Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = new Robot().createScreenCapture(screenRect);
ImageIO.write(capture, "png", new File("./screenshot.png"));

By adjusting the screenRect you could also just take a screenshot of a portion of the screen.

cello
  • 5,356
  • 3
  • 23
  • 28
  • I need to do screeshot of one specific directx\OpenGl program. I think it`s impossible with this option – Drop Sep 27 '17 at 15:00
  • why do you think that it is impossible with the provided code? – cello Sep 27 '17 at 18:02
  • it is do screenshot of desktop. As I lnow. if game doesn`t visible, it`s just do desktopscreen anyway. – Drop Sep 27 '17 at 18:16
  • What should be in the screenshot of a non-visible game? I'm confused. Maybe that's why your screenshots are black, because the window does not yet show? – cello Sep 27 '17 at 18:19
  • When game not visible, I need to get nothing. I don`t want to spy for users. Thei desktop non interesting for me. it is black even game is visible. I can get a picture just if game run in window. – Drop Sep 27 '17 at 18:33
  • `Robot#createScreenCapture()` has a messy behavior when HiDPI scaling is enabled. With Java 8 it expects a rectangle in the unscaled screen coordinates, this is inconsistent with the dimension returned by `Toolkit#getScreenSize()` and `GraphicsConfiguration#getBounds()` which are scaled. With Java 11 its slightly more consistent and `Robot#createScreenCapture()` takes a scaled rectangle, but the image returned is also scaled and not pixel equivalent to the actual image displayed on the screen. For these reasons using the Windows API directly probably makes sense. – Emmanuel Bourg Nov 13 '19 at 16:43