Я программирую наложение на Java, показывающее информацию для нескольких окон.
Мне нужно, чтобы он следовал за окном, которое он отслеживает, и для этого я регулярно беру информацию о текущих окнах, чтобы обновлять позицию моего наложения. Но мне также нужно знать, видны ли окна, чтобы скрыть наложение, если нет. В идеале я должен иметь возможность делать все это в режиме реального времени, но я боюсь, что это слишком требовательно к производительности.
Я делаю все это с JNA
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
HWND FindWindow(String lpClassName, String lpWindowName);
int GetWindowRect(HWND handle, int[] rect);
boolean IsWindowVisible(HWND handle); // always true if window exist
}
public static int[] getWindowInformation(String windowName) {
int[] rectangle = {0,0,0,0};
HWND hwnd = User32.INSTANCE.FindWindow(null, windowName);
User32.INSTANCE.GetWindowRect(hwnd, rectangle);
boolean res = User32.INSTANCE.IsWindowVisible(hwnd);
System.out.println(windowName + " is visible ? " + res);
return rectangle;
}
Вот мой код, вы можете видеть, что я попробовал «IsWindowVisible» после того, как полностью прочитал User32 API JNA, но он не делает то, что я хочу.
Ваша интуиция в использовании IsWindowVisible
от User32
хороша. JNA фактически реализовала это в своем классе WindowUtils.
List<DesktopWindow> windows = WindowUtils.getAllWindows(true);
Булев параметр — onlyVisibleWindows
.
Обратите внимание, что «видимый» здесь относится к состоянию самого окна, а не к тому, свернуто ли оно (может иметь внеэкранную или «нулевую» координату) или «позади» или «поверх» других окон и, таким образом, видимо для пользователя. пользователь. Из документации IsWindowVisible (обратите внимание на второй абзац):
Если указанное окно, его родительское окно, его родительское родительское окно и т. д. имеют стиль WS_VISIBLE, возвращаемое значение не равно нулю. В противном случае возвращаемое значение равно нулю.
Поскольку возвращаемое значение указывает, имеет ли окно стиль WS_VISIBLE, оно может быть ненулевым, даже если окно полностью закрыто другими окнами.
Чтобы определить, частично или полностью закрыто окно, вам нужно будет оценить его прямоугольник locAndSize
относительно всех окон «перед» ним, используя Z-порядок. Вы можете сделать это попиксельно или просто оценить угловые точки, в зависимости от того, как вы хотите обрабатывать частично закрытые окна.
Метод JNA getAllWindows()
возвращает список (отфильтрованный по видимости) JNA DesktopWindow
, инкапсулирующих эти поля:
private HWND hwnd;
private String title;
private String filePath;
private Rectangle locAndSize;
Внутри вы можете увидеть реализацию во внутреннем классе W32WindowUtils
, который использует функцию обратного вызова, отправленную в функцию User32
EnumWindows
:
@Override
public List<DesktopWindow> getAllWindows(final boolean onlyVisibleWindows) {
final List<DesktopWindow> result = new LinkedList<DesktopWindow>();
final WNDENUMPROC lpEnumFunc = new WNDENUMPROC() {
@Override
public boolean callback(final HWND hwnd, final Pointer arg1) {
try {
final boolean visible = !onlyVisibleWindows
|| User32.INSTANCE.IsWindowVisible(hwnd);
if (visible) {
final String title = getWindowTitle(hwnd);
final String filePath = getProcessFilePath(hwnd);
final Rectangle locAndSize = getWindowLocationAndSize(hwnd);
result.add(new DesktopWindow(hwnd, title, filePath,
locAndSize));
}
} catch (final Exception e) {
// FIXME properly handle whatever error is raised
e.printStackTrace();
}
return true;
}
};
if (!User32.INSTANCE.EnumWindows(lpEnumFunc, null))
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
return result;
}
Я поддерживаю проект OSHI на основе JNA и реализовал эту кросс-платформу через new SystemInfo().getOperatingSystem().getDesktopWindows()
, которая использует приведенную выше реализацию в Windows и добавляет информацию из других функций для получения порядка окон. Список возврата OSHI включает эти поля, и возвращаемый список уже отсортирован по order
, чтобы помочь вам определить видимость для пользователя:
private final long windowId;
private final String title;
private final String command;
private final Rectangle locAndSize;
private final long owningProcessId;
private final int order;
private final boolean visible;
@NoahFraiture «Видимость» окна также зависит от Z-порядка и местоположения. Для любого заданного пикселя на экране вы найдете самое переднее окно (порядок Z), которое содержит пиксель в своем locAndSize
. Вы можете перебирать окна по порядку спереди назад, проверяя пиксели.
Спасибо за ответ. На самом деле это не работает так, как я хочу. В нем говорится, что на моем компьютере открываются все окна (и даже больше, например, окно с двумя параметрами?). Я хочу знать, какие окна действительно видны, чтобы скрыть наложение, когда в этом нет необходимости. Как если бы это было частью оригинального окна