Как вы можете получить дескриптор процесса chrome в java, используя JNA

Я новичок в JNA, и мне нужно сделать снимок экрана хромированного окна с использованием java и JNA, у меня уже есть функция для создания снимков экрана данного окна с использованием этого кода:

  public BufferedImage capture(WinDef.HWND hWnd) {

    WinDef.HDC hdcWindow = User32.INSTANCE.GetDC(hWnd);
    WinDef.HDC hdcMemDC = GDI32.INSTANCE.CreateCompatibleDC(hdcWindow);



    WinDef.RECT bounds = new WinDef.RECT();
    User32Extra.INSTANCE.GetClientRect(hWnd, bounds);

    int width = bounds.right - bounds.left;
    int height = bounds.bottom - bounds.top;

    WinDef.HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcWindow, width, height);

    WinNT.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);

    WinGDI.BITMAPINFO bmi = new WinGDI.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);

    return image;

}

затем я использую следующий код для сохранения буферизованного изображения:

     BufferedImage image;

     WinDef.HWND hWnd = User32.INSTANCE.FindWindow(null, "notepad - untitled");
                image = capture(hWnd);
                File outputfile = new File("image.jpg");
                try {
                    ImageIO.write(image, "jpg", outputfile);
                } catch (IOException e) {
                    e.printStackTrace();
                }

это работает для некоторых приложений, например. блокнот, но не для хрома, для хрома он просто выдает исключение недопустимого аргумента, потому что программа пытается сделать снимок экрана с шириной и высотой, которые в основном равны 0, поскольку процесс не был найден, полное исключение:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Allocation size must be greater than zero
at com.sun.jna.Memory.<init>(Memory.java:111)
at de.xliquid.stadiarpc.Main.capture(Main.java:103)
at de.xliquid.stadiarpc.Main$1.run(Main.java:56)
at com.sun.javafx.scene.KeyboardShortcutsHandler.processAccelerators(KeyboardShortcutsHandler.java:347)
at com.sun.javafx.scene.KeyboardShortcutsHandler.dispatchBubblingEvent(KeyboardShortcutsHandler.java:163)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$357(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$152(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)

Я пытался использовать текущее название хрома, но это не сработало, и я думаю, что лучшим решением было бы просто получить дескриптор первой вкладки хрома. К сожалению, я действительно не знаю, с чего начать здесь. Может ли кто-нибудь сказать мне, что я могу сделать? Заранее спасибо.

🤔 А знаете ли вы, что...
С Java можно создавать апплеты - встроенные приложения, запускаемые в браузере.


1
194
1

Ответ:

Решено

Здесь может помочь класс JNA WindowUtils . Метод getAllWindows() вернет List<DesktopWindow>, где каждый экземпляр DesktopWindow включает в себя как заголовок (чтобы соответствовать вашему процессу Chrome), так и дескриптор HWND этого окна.

У DesktopWindow также есть Rectangle с размерами местоположения и размера, поэтому вы можете скопировать соответствующие размеры с самого рабочего стола, например, этот простой однострочник:

BufferedImage screenShot = new Robot().createScreenCapture(rectangle);

Ответы на этот вопрос StackOverlow определяют несколько других вариантов создания снимка экрана всего окна; просто замените Rectangle, который вы получаете от класса DesktopWindow, соответствующим образом (или используйте свой собственный код выше с размерами прямоугольника).

В качестве альтернативы, если вам не нужна вся информация из класса WindowUtils, вы можете напрямую использовать функцию WinAPI EnumWindows для прямого повторения окон и захвата только той информации, которая вам нужна. Это функция, которую WindowUtils использует внутри, поэтому ее исходный код будет хорошей отправной точкой для упрощения.