Acquire windowHandle of given Swing/AWT window in JNI dll code?

Acquire windowHandle of given Swing/AWT window in JNI dll code?

If I create the following dll (delphi pascal pseudo-code, dont mind naming errors). And winapi method is just an example but should give you the idea.


// delphi jni.dll helper method
function doSometing(javaWindow: HWND): boolean;
begin
  Result := IsWindowVisible(javawindow); // call WinAPI method with given window handle
end;
. . . 
// somewhere in java
public void doSomething() {
   // any method to acquire native HWND handle and give it as a parameter?
   boolean b = doSomething(myFrame);
   System.out.println(b);
}

Can I call it from Java and give a swing/awt window handle as a parameter. Or should I give frame instance as a parameter and then somehow use it inside the native code?

The later… use a Frame and get the HWND in the native code. JAWT (part of JNI) is built for this. Take a look at the jawt header files from the JDK and google for some examples.

Thx, used JAWT keyword and Mr Google gave few helpful links
http://forums.java.sun.com/thread.jspa?threadID=453581&messageID=2145897
http://today.java.net/pub/a/today/2003/12/08/swing.html?page=last&x-maxdepth=0

Most code is c/c++ but I try to study it and convert to ObjectPascal.

One thing to note about the code sample in the dorum post at java.sun.com… They mess around with finding the java home folder to load the AWT DLL. It can be done MUCH easier than that. Just use System.loadLibrary(“jawt”); on the Java side.

Thats what I looked and wondered is it really necessary to load library that way. Looks a rather fragile trying to find a right jawt.dll version to be loaded.

They use hAWT handle to get pointer to JAWT_GetAWT function. If library is loaded at java side, can I then just call “JAWT_GetAWT(env, &jawt)” function directly in a native code and it should work fine?

javaforum code example:
…clip…
// Get a reference to the AWT DLL
hAWT = LoadLibrary ((LPCTSTR)buf);
if (!hAWT) return 1;
JAWT_GetAWT = (PJAWT_GetAWT)GetProcAddress((HMODULE)hAWT, “_JAWT_GetAWT@8”);
// reference to JAWT structure containing native jawt functions
result = JAWT_GetAWT (env, &jawt);
// This call gets the JAWT_DrawingSurface
jds = jawt.GetDrawingSurface (env, canvas);.
…clip…

EDIT:
Ok, I looked at the other today.java.net article and it had I think more clean example. Sources were hidden in a https://mad-chatter.dev.java.net/ site. It does not load JAWT.dll library either in native or java side. It just loads WindowUtil.dll library and nothing more.

One thing I dont understand about native method arguments;
// the actual native method declaration in java code
public native void flash(Component c, boolean bool);

// use flash method somewhere in java code
flash(frame,true);

// native method declaration
JNIEXPORT void JNICALL Java_org_joshy_jni_WindowUtil_flash(
JNIEnv * env, jobject canvas, jobject component, jboolean bool) { … }

Now this method has “jobject canvas, jobject component, jboolean bool” arguments. And code uses component argument to get a window handle for given java side frame. But what is canvas argument and where it came from, java side method has only two arguments. And canvas argument is not used in native side?


#include <assert.h>
#include "jawt_md.h"
#include "org_joshy_jni_WindowUtil.h"

JNIEXPORT void JNICALL Java_org_joshy_jni_WindowUtil_flash(
JNIEnv * env, jobject canvas, jobject component, jboolean bool) {
    JAWT awt;
    JAWT_DrawingSurface* ds;
    JAWT_DrawingSurfaceInfo* dsi;
    JAWT_Win32DrawingSurfaceInfo* dsi_win;
    jboolean result;

    jint lock;

    // Get the AWT
    awt.version = JAWT_VERSION_1_3;
    result = JAWT_GetAWT(env, &awt);
    assert(result != JNI_FALSE);
    // Get the drawing surface
    ds = awt.GetDrawingSurface(env, component);
    if(ds == NULL)
        return;
    // Lock the drawing surface
    lock = ds->Lock(ds);
    assert((lock & JAWT_LOCK_ERROR) == 0);

    // Get the drawing surface info
    dsi = ds->GetDrawingSurfaceInfo(ds);

    // Get the platform-specific drawing info
    dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;

    FlashWindow(dsi_win->hwnd,bool);

    // Free the drawing surface info
    ds->FreeDrawingSurfaceInfo(dsi);
    // Unlock the drawing surface
    ds->Unlock(ds);
    // Free the drawing surface
    awt.FreeDrawingSurface(ds);
}

/////////////////////////////
// JAVA SIDE
/////////////////////////////
package org.joshy.jni;
import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Canvas;
import java.awt.*;

public class WindowUtil extends Canvas {
    // load the native dll
    static {
        System.loadLibrary("WindowUtil");
    }
    // the actual native method
    public native void flash(Component c, boolean bool);

    /**
    <p>A utility method that flashes the window on and off. This method
    will not block to wait for the flashing.
     Instead it will spawn an thread to do the flashing.
    </p>

     @param frame The JFrame to be flashed
     @param intratime The amount of time between the on and off states of a single flash
     @param intertime The amount of time between different flashes
     @param count The number of times to flash the window
    */
    public void flash(final JFrame frame, final int intratime, final int intertime, final int count) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    // flash on and off each time
                    for(int i=0; i<count; i++) {
                        flash(frame,true);
                        Thread.sleep(intratime);
                        flash(frame,true);
                        Thread.sleep(intertime);
                    }
                    // turn the flash off
                    flash(frame,false);
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                }
        }}).start();
    }

    public static void main(String[] args) throws Exception {
        final JFrame frame = new JFrame();
        JButton button = new JButton("stuff");
        frame.getContentPane().add(button);
        final WindowUtil winutil = new WindowUtil();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                winutil.flash(frame,750,1500,5);
            }
        });
        frame.pack();
        frame.show();
    }

}

The canvas method is the class/object containing the native method. If the native method is not static it is equivalent to “this” in Java.
The component would need to be heavyweight to have a window handle on the native side, otherwise the heavyweight parent container (e.g Frame) would be used.