portable para descargar java windows cross-platform

java - portable - descargar launch4j para windows 10 64 bits



Windows: ¿cómo obtener una lista de todas las ventanas visibles? (3)

¿Se puede hacer esto?

Sí, aunque tendría que registrar un hook para obtener lo que desea con respecto a una devolución de llamada. Probablemente necesitarías usar un gancho de devolución de llamada CBTProc , al que se llama cuando:

activar, crear, destruir, minimizar, maximizar, mover o ajustar el tamaño de una ventana; antes de completar un comando del sistema; antes de eliminar un evento de mouse o teclado de la cola de mensajes del sistema; antes de ajustar el enfoque del teclado; o antes de sincronizar con la cola de mensajes del sistema

Sin embargo, tenga en cuenta que no creo que tales enganches funcionen en las ventanas de la Consola porque son el dominio del kernel, no de Win32.

¿hay API de Windows bien documentadas (y funcionan según sus especificaciones) que permiten hacer eso?

Sí. Puede usar las funciones GetTopWindow y GetNextWindow para obtener todos los manejadores de ventanas en el escritorio en el orden Z correcto.

¿Es fácil registrar una devolución de llamada cada vez que cambia una ventana? (si se cambia de tamaño, se mueve, se trae hacia atrás / adelante o si aparece una nueva ventana, etc.)

Ver primera respuesta :)

¿Cuáles serían las trampas?

Ver primera respuesta :)

Pregunta extra: imagine que necesitaría escribir un pequeño archivo .exe escribiendo los nombres / posición / tamaño de las ventanas en un archivo temporal cada vez que haya un cambio de ventana en la pantalla, ¿cuánto tiempo sería el programa aproximadamente en el idioma de su elección y durante cuánto tiempo? necesitarías escribirlo?

Unos cientos de líneas de C, y un par de horas. Aunque tendría que usar alguna forma de sondeo, nunca antes había hecho ganchos. Si necesitara los ganchos tardaría un poco más.

(por supuesto, vuelva a etiquetar con la tecnología relevante: no sé cuáles son :)

Probablemente vendré más tarde con preguntas más detalladas, sobre detalles específicos, pero por ahora estoy tratando de comprender el "panorama general": estoy buscando una manera de enumerar las "ventanas visibles reales" en Windows. Por "ventana visible real" quiero decir exactamente eso: lo que un usuario llamaría una "ventana". Necesito una forma de obtener una lista de todas estas ventanas visibles, en orden Z.

Tenga en cuenta que realmente necesito hacer eso. Ya lo hice en OS X (donde es un verdadero dolor de cabeza, especialmente si quieres admitir OS X 10.4, porque OS X no tiene una API de Windows conveniente) y ahora necesito hacerlo bajo Windows.

Aquí hay un ejemplo, supongamos que hay tres ventanas visibles en la pantalla, como esta:

+------------------------------------------+ | | | +=============+ | | | | | | | A +--------------------------+ | | | | | C | | B | | | +--------------------------+ | | | | +-----------| |----------------+ | | +-------------+

Entonces necesito recuperar una lista como esta:

windows B is at (210,40) windows A is at (120,20) windows C is at (0,0)

Luego, si el usuario (o el sistema operativo) lleva la ventana A al frente, se convierte en:

+------------------------------------------+ | | | +=============+ | | | | | | | A |---------------------+ | | | | | C | | B | | | |---------------------+ | | | | +-----------| |----------------+ | | +-------------+

Y recibo (idealmente) una devolución de llamada que me da esto:

windows A is at (120,20) windows B is at (210,40) windows C is at (0,0)

Hacer esto en OS X requiere el uso de hacks increíblemente extraños (como ordenar al usuario que active "Habilitar acceso para dispositivo de asistencia" ), pero lo he hecho en OS X y funciona (en OS X, no lo hice puedo obtener una devolución de llamada cada vez que se producen algunos cambios en la ventana, por lo que estoy sondeando, pero tengo que funcionar).

Ahora quiero hacer esto en Windows (realmente lo hago, no tengo dudas) y tengo algunas preguntas:

  • ¿Se puede hacer esto?

  • ¿hay API de Windows bien documentadas (y funcionan según sus especificaciones) que permiten hacer eso?

  • ¿Es fácil registrar una devolución de llamada cada vez que cambia una ventana? (si se cambia de tamaño, se mueve, se trae hacia atrás / adelante o si aparece una nueva ventana, etc.)

  • ¿Cuáles serían las trampas?

Sé que esta pregunta no es específica, por lo que he tratado de describir mi problema con la mayor claridad posible (incluido un buen arte ASCII para el que puedes promocionar esto): por ahora estoy viendo el "panorama general". Quiero saber qué implica hacer algo así en Windows.

Pregunta extra: imagine que necesitaría escribir un pequeño archivo .exe escribiendo los nombres / posición / tamaño de las ventanas en un archivo temporal cada vez que haya un cambio de ventana en la pantalla, ¿cuánto tiempo sería el programa aproximadamente en el idioma de su elección y durante cuánto tiempo? necesitarías escribirlo?

(Una vez más, estoy tratando de obtener el "panorama general" para entender lo que está funcionando aquí)


Para enumerar las ventanas de nivel superior, debe usar EnumWindows lugar de GetTopWindow / GetNextWindow, ya que EnumWindows devuelve una vista coherente del estado de la ventana. Se arriesga a obtener información inconsistente (como informar sobre ventanas eliminadas) o bucles infinitos utilizando GetTopWindow / GetNextWindow, cuando las ventanas cambian de orden z durante la iteración.

El EnumWindows utiliza una devolución de llamada. En cada llamada de la devolución de llamada obtendrá un identificador de ventana. Las coordenadas de la pantalla de la ventana se pueden obtener pasando ese identificador a GetWindowRect . Su devolución de llamada crea una lista de las posiciones de la ventana en orden z.

Puedes usar el sondeo y construir la lista de ventanas repetidamente. O bien, configura un CBTHook para recibir notificaciones de cambios de ventana. No todas las notificaciones de TCC provocarán cambios en el orden, la posición o la visibilidad de las ventanas de nivel superior, por lo que es aconsejable volver a ejecutar EnmWindows para crear una nueva lista de posiciones de ventana en orden z y comparar esto con la lista anterior antes de seguir procesando la lista. para que el procesamiento posterior se realice solo cuando se ha producido un cambio real.

Tenga en cuenta que con el enganche, no puede mezclar 32 y 64 bits. Si está ejecutando una aplicación de 32 bits, recibirá notificaciones de los procesos de 32 bits. Del mismo modo para 64 bits. Por lo tanto, si desea monitorear todo el sistema en una máquina de 64 bits, parece que es necesario ejecutar dos aplicaciones. Mi razonamiento viene de leer esto:

SetWindowsHookEx puede usarse para inyectar una DLL en otro proceso. Una DLL de 32 bits no se puede inyectar en un proceso de 64 bits, y una DLL de 64 bits no se puede inyectar en un proceso de 32 bits. Si una aplicación requiere el uso de enlaces en otros procesos, se requiere que una aplicación de 32 bits llame a SetWindowsHookEx para inyectar una DLL de 32 bits en procesos de 32 bits, y una aplicación de 64 bits llame a SetWindowsHookEx para inyectar una DLL en procesos de 64 bits. Las DLL de 32 bits y 64 bits deben tener nombres diferentes. (De la página de la API de SetWindowsHookEx).

Cuando esté implementando esto en Java, es posible que desee ver JNA , ya que simplifica mucho el acceso de escritura a bibliotecas nativas (código de llamada en java) y elimina la necesidad de su propia DLL JNI nativa.

EDITAR: usted preguntó cuánto código es y cuánto tiempo para escribir. Aquí está el código en java

import com.sun.jna.Native; import com.sun.jna.Structure; import com.sun.jna.win32.StdCallLibrary; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class Main { public static void main(String[] args) { Main m = new Main(); 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) { if (User32.instance.IsWindowVisible(hWnd)) { RECT r = new RECT(); User32.instance.GetWindowRect(hWnd, r); if (r.left > -32000) { // If it''s not minimized byte[] buffer = new byte[1024]; User32.instance.GetWindowTextA(hWnd, buffer, buffer.length); String title = Native.toString(buffer); inflList.add(new WindowInfo(hWnd, r, title)); } } 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 interface WndEnumProc extends StdCallLibrary.StdCallCallback { boolean callback(int hWnd, int lParam); } public static interface User32 extends StdCallLibrary { final User32 instance = (User32) Native.loadLibrary ("user32", User32.class); final int GW_HWNDNEXT = 2; 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); } public static class RECT extends Structure { public int left, top, right, bottom; } public static class WindowInfo { public final int hwnd; public final RECT rect; public final 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); } } }

He hecho la mayoría de las clases internas relacionadas y las clases internas de interfaces para mantener el ejemplo compacto y pasable para una compilación inmediata. En una implementación real, serían clases regulares de nivel superior. La aplicación de la línea de comandos imprime las ventanas visibles y su posición. Lo ejecuté tanto en jvm de 32 bits como en 64 bits, y obtuve los mismos resultados para cada uno.

EDIT2: Código actualizado para incluir orden z. Se utiliza GetNextWindow. En una aplicación de producción, probablemente debería llamar a GetNextWindow dos veces para obtener los valores siguientes y anteriores y verificar que sean coherentes y que sean válidos para los manejadores de ventanas.