Как вы можете получить дескриптор процесса 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)

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


person xliquid    schedule 14.12.2020    source источник
comment
Я одобряю ваше мужество, потому что эта JNA... разве она не сломала вашу машину??   -  person gpasch    schedule 15.12.2020
comment
Да, этот код не лучшее решение, но пока работает.   -  person xliquid    schedule 15.12.2020


Ответы (1)


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

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

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

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

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

person Daniel Widdis    schedule 14.12.2020
comment
Ответы на этот вопрос StackOoverlow определяют несколько других вариантов создания снимка экрана всего окна: не говорите мне, что все они полагаются на робота! - person gpasch; 15.12.2020
comment
Нет, они не. Это была просто удобная острота. :) Кроме того, Ой, опечатка. - person Daniel Widdis; 15.12.2020
comment
сработало отлично спасибо :D - person xliquid; 15.12.2020