En Java Swing, ¿cómo se obtiene una referencia de manejador de ventana Win32 (hwnd) a una ventana?

En Java 1.4 puede usar ((SunToolkit) Toolkit.getDefaultToolkit ()). GetNativeWindowHandleFromComponent () pero eso fue eliminado.

Parece que tienes que usar JNI para hacer esto ahora. ¿Tiene el código JNI y el código de ejemplo de Java para hacer esto?

Necesito esto para llamar a las llamadas a la API Win32 GetWindowLong y SetWindowLong, lo que se puede hacer a través de la biblioteca Jawin.

Me gustaría algo muy preciso para poder pasar una referencia al JDialog o JFrame y obtener el identificador de la ventana.

La transparencia de swing usando JNI puede estar relacionada.

No tiene que escribir ningún código C / JNI. De Java:

import sun.awt.windows.WComponentPeer; public static long getHWnd(Frame f) { return f.getPeer() != null ? ((WComponentPeer) f.getPeer()).getHWnd() : 0; } 

Advertencias:

  • Esto usa un paquete sun *. Obviamente, esto no es API pública. Pero es poco probable que cambie (y creo que es menos probable que se rompa que las soluciones anteriores).
  • Esto se comstackrá y ejecutará solo en Windows. Tendría que convertir esto en código de reflexión para que sea portátil.

Este pequeño método JNI acepta un título de ventana y devuelve el identificador de ventana correspondiente.

 JNIEXPORT jint JNICALL Java_JavaHowTo_getHwnd (JNIEnv *env, jclass obj, jstring title){ HWND hwnd = NULL; const char *str = NULL; str = (*env)->GetStringUTFChars(env, title, 0); hwnd = FindWindow(NULL,str); (*env)->ReleaseStringUTFChars(env, title, str); return (jint) hwnd; } 

ACTUALIZAR:

Con JNA, es un poco más fácil. Hice un pequeño ejemplo que encuentra el mango y lo uso para llevar el progtwig al frente.

El siguiente código le permite pasar un componente para obtener el identificador de ventana (HWND). Para asegurarse de que un Componente tiene un manejador de ventana correspondiente, invoqueLightWeight () en el Componente y verifique que sea falso. Si no es así, intente con sus padres llamando a Component.getParent ().

Código Java:

 package win32; public class Win32 { public static native int getWindowHandle(Component c); } 

Archivo de encabezado main.h:

 /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class win32_Win32 */ #ifndef _Included_win32_Win32 #define _Included_win32_Win32 #ifdef __cplusplus extern "C" { #endif /* * Class: win32_Win32 * Method: getWindowHandle * Signature: (Ljava/awt/Component;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_win32_Win32_getWindowHandle (JNIEnv *, jclass, jobject); #ifdef __cplusplus } #endif #endif 

La fuente C main.c:

 #include #include  #include  #include  HMODULE _hAWT = 0; JNIEXPORT jint JNICALL Java_win32_Win32_getWindowHandle (JNIEnv * env, jclass cls, jobject comp) { HWND hWnd = 0; typedef jboolean (JNICALL *PJAWT_GETAWT)(JNIEnv*, JAWT*); JAWT awt; JAWT_DrawingSurface* ds; JAWT_DrawingSurfaceInfo* dsi; JAWT_Win32DrawingSurfaceInfo* dsi_win; jboolean result; jint lock; //Load AWT Library if(!_hAWT) //for Java 1.4 _hAWT = LoadLibrary("jawt.dll"); if(!_hAWT) //for Java 1.3 _hAWT = LoadLibrary("awt.dll"); if(_hAWT) { PJAWT_GETAWT JAWT_GetAWT = (PJAWT_GETAWT)GetProcAddress(_hAWT, "_JAWT_GetAWT@8"); if(JAWT_GetAWT) { awt.version = JAWT_VERSION_1_4; // Init here with JAWT_VERSION_1_3 or JAWT_VERSION_1_4 //Get AWT API Interface result = JAWT_GetAWT(env, &awt); if(result != JNI_FALSE) { ds = awt.GetDrawingSurface(env, comp); if(ds != NULL) { lock = ds->Lock(ds); if((lock & JAWT_LOCK_ERROR) == 0) { dsi = ds->GetDrawingSurfaceInfo(ds); if(dsi) { dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; if(dsi_win) { hWnd = dsi_win->hwnd; } else { hWnd = (HWND) -1; } ds->FreeDrawingSurfaceInfo(dsi); } else { hWnd = (HWND) -2; } ds->Unlock(ds); } else { hWnd = (HWND) -3; } awt.FreeDrawingSurface(ds); } else { hWnd = (HWND) -4; } } else { hWnd = (HWND) -5; } } else { hWnd = (HWND) -6; } } else { hWnd = (HWND) -7; } return (jint)hWnd; } 

Los dos métodos anteriores funcionan bien, pero ambos devuelven un HWND como java int (32 bits). esto está bien para una plataforma de 32 bits, pero es poco probable que su aplicación funcione en una plataforma de 64 bits. Cambiaría los tipos de devolución a longs (64bits) ya que esto se comportará correctamente tanto en sistemas de 64 bits como en sistemas de 32 bits (solo tendrá que volver a comstackr el archivo DLL).

Encontré esto: http://jna.java.net/javadoc/com/sun/jna/Native.html#getWindowID(java.awt.Window )

JNA te permite llamar a bibliotecas nativas sin tener que escribir el código nativo jni. Resulta que la biblioteca en sí tiene un método que toma una ventana y produce un int, presumiblemente un identificador (¿o un puntero?) Que con suerte funciona en todas las plataformas.

En la biblioteca JNA, vemos que el uso de Native AWT en Java 5 y 6 UnsatisfiedLinkError cuando se ejecuta sin cabeza, por lo tanto, utilice enlaces dynamics. Consulte el método Java_com_sun_jna_Native_getWindowHandle0 en https://github.com/twall/jna/blob/master/native/dispatch.c .

Es lo mismo que la respuesta de Jared MacD, pero utiliza la reflexión para que el código pueda comstackrse y cargarse en una computadora que no sea de Windows. Por supuesto, fallará si intentas llamarlo.

 import java.awt.Frame; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class WindowHandleGetter { private static final Logger log = LoggerFactory.getLogger(WindowHandleGetter.class); private final Frame rootFrame; protected WindowHandleGetter(Frame rootFrame) { this.rootFrame = rootFrame; } protected long getWindowId() { try { Frame frame = rootFrame; // The reflection code below does the same as this // long handle = frame.getPeer() != null ? ((WComponentPeer) frame.getPeer()).getHWnd() : 0; Object wComponentPeer = invokeMethod(frame, "getPeer"); Long hwnd = (Long) invokeMethod(wComponentPeer, "getHWnd"); return hwnd; } catch (Exception ex) { log.error("Error getting window handle"); } return 0; } protected Object invokeMethod(Object o, String methodName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class c = o.getClass(); for (Method m : c.getMethods()) { if (m.getName().equals(methodName)) { Object ret = m.invoke(o); return ret; } } throw new RuntimeException("Could not find method named '"+methodName+"' on class " + c); } }