Как захватить выбранный экран другого приложения, используя Java? - PullRequest
10 голосов
/ 21 января 2009

Мы пытаемся разработать утилиту захвата экрана.

Как мы можем захватить выбранный экран другого приложения, используя Java? А как добавить выноску на захваченный экран?

Ответы [ 8 ]

11 голосов
/ 31 января 2009

Основываясь на описании проекта Prajakta , я полагаю, что некоторые объяснения манипуляции со снимком экрана в порядке (я думаю, что Джон отлично справился с объяснением , как сделать снимок экрана, используя java.awt.Робот класс ). Помните, как сказал Стив Маклеод , Java может не иметь возможности автоматически определять местоположение окна, которое вы хотите захватить на экране. Это важно, потому что класс Robot должен знать это местоположение, автоматически или вручную от вас.

Выноски, текст, изображения и т. Д. Можно добавить к снимку экрана через объект Graphics2D, который вы получаете, когда вызываете метод createGraphics () снимка экрана BufferedImage . Я настоятельно рекомендую вам ознакомиться с API Graphics2D , чтобы лучше понять, на что он способен. Я также рекомендую найти некоторые учебные пособия, возможно, начиная с учебника по 2D-графике от Sun . Книга под названием " Грязные богатые клиенты " также может пригодиться.

Если вы, наконец, хотите сохранить этот измененный снимок экрана, вы можете использовать один из методов записи класса ImageIO .

Вот очень простой пример от начала до конца. Это зависит от вас, чтобы заполнить все необходимые детали.

Надеюсь, это немного поможет!

Robot robot = new Robot();

// The hard part is knowing WHERE to capture the screen shot from
BufferedImage screenShot = robot.createScreenCapture(x, y, width, height);
Graphics2D graphics = screenShot.createGraphics();

// Add a label to the screen shot
Color textColor = Color.RED;
graphics.setColor(textColor);
graphics.drawString("Some text", textX, textY);

// Save your screen shot with its label
ImageIO.save(screenShot, "png", new File("myScreenShot.png"));
5 голосов
/ 22 января 2009
Robot r = new Robot();
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
Image i = r.createScreenCapture( 0, 0, d.width, d.height );

должно получить целое изображение всего экрана. не уверен, что это даст вам все, если у вас есть несколько мониторов, хотя ...

3 голосов
/ 31 января 2009

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

У вас есть два подхода, если опция полноэкранная, вам не о чем беспокоиться, следуйте описанному выше подходу Robot.

Если аппликатин для нужной области:

  1. Запустите желаемое приложение.

  2. Возьмите полный экран рабочего стола.

  3. Создание полноэкранного приложения с использованием снимка экрана в качестве фона, ТОЛЬКО для того, чтобы пользователь мог выбрать область для захвата изображения (вы начинаете с небольшого квадрата и позволяете пользователю перетаскивать, пока он не создаст нужный экран захват)

  4. Передайте эту информацию роботу и сделайте скриншоты из этой области.

Примерно так:

альтернативный текст http://img136.imageshack.us/img136/8622/screencapturebb3.png

Если вам не нравится возможность использовать полный скриншот в качестве фона, вы можете использовать прозрачное окно .

И сделать то же самое: -)

Второй вариант - попытаться определить границы, анализируя изображения, но, честно говоря, я не думаю, что это того стоит.

Есть третий вариант, но это секрет.

3 голосов
/ 21 января 2009

Возможно, класс java.awt.Robot поможет с снимками экрана, хотя я не думаю, что он способен находить отдельные окна. Что касается этих «вызовов», класс Robot может также вызывать щелчки мыши и нажатия клавиш, если вы это имеете в виду.

2 голосов
/ 21 января 2009

Вам потребуется предоставить более конкретную информацию, чтобы получить значимую помощь. Для начала, с какими операционными системами это должно работать? Нужно ли вам захватывать содержимое отдельных окон или буквально целых дисплеев (вы использовали неоднозначный термин «выбранный экран другого приложения» в исходном посте) Что конкретно вы хотите видеть, когда вы «добавляете выноску на захваченный экран»?

1 голос
/ 08 ноября 2017

С помощью этого кода я могу создавать экраны определенных окон в windows10, не забывайте о зависимости.

Кредиты перейти на: Windows: как получить список всех видимых окон?

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.5.0</version>
</dependency>

Код:

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.imageio.ImageIO;

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;

public class Main {
    public static void main(String[] args) throws AWTException, IOException {

        int hWnd = User32.instance.FindWindowA(null, "Minesweeper X");
        WindowInfo w = getWindowInfo(hWnd);
        User32.instance.SetForegroundWindow(w.hwnd);
        BufferedImage createScreenCapture = new Robot().createScreenCapture(new Rectangle(w.rect.left, w.rect.top, w.rect.right - w.rect.left, w.rect.bottom - w.rect.top));
        ImageIO.write(createScreenCapture, "png", new File("screen.png"));

        // listAllWindows();
    }

    private static void listAllWindows() throws AWTException, IOException {
        final List<WindowInfo> inflList = new ArrayList<WindowInfo>();
        final List<Integer> order = new ArrayList<Integer>();
        int top = User32.instance.GetTopWindow(0);
        while (top != 0) {
            order.add(top);
            top = User32.instance.GetWindow(top, User32.GW_HWNDNEXT);
        }

        User32.instance.EnumWindows(new WndEnumProc() {
            public boolean callback(int hWnd, int lParam) {
                WindowInfo info = getWindowInfo(hWnd);
                inflList.add(info);
                return true;
            }

        }, 0);
        Collections.sort(inflList, new Comparator<WindowInfo>() {
            public int compare(WindowInfo o1, WindowInfo o2) {
                return order.indexOf(o1.hwnd) - order.indexOf(o2.hwnd);
            }
        });
        for (WindowInfo w : inflList) {
            System.out.println(w);
        }
    }

    public static  WindowInfo getWindowInfo(int hWnd) {
        RECT r = new RECT();
        User32.instance.GetWindowRect(hWnd, r);
        byte[] buffer = new byte[1024];
        User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
        String title = Native.toString(buffer);
        WindowInfo info = new WindowInfo(hWnd, r, title);
        return info;
    }

    public static interface WndEnumProc extends StdCallLibrary.StdCallCallback {
        boolean callback(int hWnd, int lParam);
    }

    public static interface User32 extends StdCallLibrary {
        public static final String SHELL_TRAY_WND = "Shell_TrayWnd";
        public static final int WM_COMMAND = 0x111;
        public static final int MIN_ALL = 0x1a3;
        public static final int MIN_ALL_UNDO = 0x1a0;

        final User32 instance = (User32) Native.loadLibrary("user32", User32.class);

        boolean EnumWindows(WndEnumProc wndenumproc, int lParam);

        boolean IsWindowVisible(int hWnd);

        int GetWindowRect(int hWnd, RECT r);

        void GetWindowTextA(int hWnd, byte[] buffer, int buflen);

        int GetTopWindow(int hWnd);

        int GetWindow(int hWnd, int flag);

        boolean ShowWindow(int hWnd);

        boolean BringWindowToTop(int hWnd);

        int GetActiveWindow();

        boolean SetForegroundWindow(int hWnd);

        int FindWindowA(String winClass, String title);

        long SendMessageA(int hWnd, int msg, int num1, int num2);

        final int GW_HWNDNEXT = 2;
    }

    public static class RECT extends Structure {
        public int left, top, right, bottom;

        @Override
        protected List<String> getFieldOrder() {
            List<String> order = new ArrayList<>();
            order.add("left");
            order.add("top");
            order.add("right");
            order.add("bottom");
            return order;
        }
    }

    public static class WindowInfo {
        int hwnd;
        RECT rect;
        String title;

        public WindowInfo(int hwnd, RECT rect, String title) {
            this.hwnd = hwnd;
            this.rect = rect;
            this.title = title;
        }

        public String toString() {
            return String.format("(%d,%d)-(%d,%d) : \"%s\"", rect.left, rect.top, rect.right, rect.bottom, title);
        }
    }
}
1 голос
/ 21 января 2009

Если вы хотите сделать снимок экрана определенного окна другого кода приложения, не являющегося Java, я думаю, вам придется написать некоторый нативный (то есть не Java) код. Взаимодействие между Java-приложениями и не-Java-приложениями на таком уровне затруднено.

0 голосов
/ 28 декабря 2010

Код для захвата скриншота в Java,

http://www.codinguide.com/2010/04/capture-screen-shot-from-java.html

...