Domanda

In Java 1.4 è possibile utilizzare ((SunToolkit) Toolkit.getDefaultToolkit ()). GetNativeWindowHandleFromComponent (), ma che è stato rimosso.

Sembra che si deve usare JNI a farlo ora. Avete il codice di Java e codice di esempio JNI per fare questo?

Ho bisogno di questo per chiamare il Win32 GetWindowLong e chiamate API SetWindowLong, che può essere fatto tramite la libreria Jawin.

Vorrei qualcosa di molto preciso in modo da poter passare un riferimento alla JDialog o JFrame e ottenere l'handle della finestra.

trasparenza swing usare JNI possono essere correlati.

È stato utile?

Soluzione 3

Il seguente codice permette di passare un componente per ottenere l'handle di finestra (HWND) per esso. Per assicurarsi che un componente ha un corrispondente isLightWeight martellina call () sul componente e verificare che equivale a falso. Se non lo fa, prova a suo genitore chiamando Component.getParent ().

codice Java:

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

File di intestazione main.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

Il sorgente C main.c:

#include<windows.h>
#include <jni.h>
#include <jawt.h>
#include <jawt_md.h>

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;

}

Altri suggerimenti

Non è necessario scrivere alcun / codice JNI C. Da Java:

import sun.awt.windows.WComponentPeer;

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

Avvertenze:

  • Questo utilizza un sole. * Pacchetto. Ovviamente questo non è API pubblica. Ma è improbabile che cambi (e penso meno probabilità di rottura rispetto alle soluzioni di cui sopra).
  • Questo sarà compilato ed eseguito solo su Windows. Si avrebbe bisogno di trasformare questo in codice di riflessione per questo di essere portatile.

Questo metodo poco JNI accetta un titolo della finestra e restituisce il corrispondente maniglia della finestra.

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;
 }

UPDATE:

Con la JNA, è un po 'più facile. Ho fatto un piccolo esempio che trovano la maniglia e utilizzarlo per portare il programma in primo piano.

Ho trovato questo: http: //jna.java.net/javadoc/com/sun/jna/Native.html#getWindowID(java.awt.Window )

JNA consente di richiamare le librerie native, senza dover scrivere codice nativo JNI. Si scopre che la biblioteca stessa ha un metodo che accetta una finestra e produce un int, presumibilmente una maniglia (o il puntatore?) Che funziona su tutte le piattaforme si spera.

In biblioteca JNA vediamo che l'utilizzo di Native AWT in Java 5 e 6 UnsatisfiedLinkError quando eseguito senza testa, in modo da utilizzare il collegamento dinamico. Vedere il metodo Java_com_sun_jna_Native_getWindowHandle0 in https://github.com/twall/jna/ blob / master / native / dispatch.c .

Questa è la stessa risposta di Jared MacD ma utilizza la riflessione in modo che il codice può compilare e caricare su un computer non Windows. Naturalmente non riuscirà se si tenta di chiamare.

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);

    }


}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top