In this example we will be using win32 apis like FindWindow, SetForegroundWindow, GetWindowText, GetWindow, IsWindowVisible & GetDesktopWindow in a Java application using JNI.
The first step in using JNI is to create a java file that will call our native methods.
package jniexample; /** * * @author Naveed Quadri */ public class NativeWin32 { public static final int GW_HWNDFIRST = 0; public static final int GW_HWNDLAST = 1; public static final int GW_HWNDNEXT = 2; public static final int GW_HWNDPREV = 3; public static final int GW_OWNER = 4; public static final int GW_CHILD = 5; static { System.loadLibrary("NativeWin32"); } public static native long jniFindWindow(String windowTitle); public static native boolean jniSetForegroundWindow(long hWnd); public static native String jniGetWindowText(long hWnd); public static native long jniGetWindow(long hWnd, int cmd); public static native boolean jniIsWindowVisible(long hWnd); public static native long jniGetDesktopWindow(); }
The first thing to note is the keyword 'native'. This tells the compiler that this method will be accessed from an external library.
The second thing to note is this code snippet. This loads the dll file, NativeWin32.dll
static { System.loadLibrary("NativeWin32"); }
Now lets generate the header the file.
//This compiles the java file
javac jniexample/NativeWin32.java
//This generates the jni header file
javah -jni jniexample.NativeWin32
The function names in the header file should be in the order of
Java_<packageName>_
Now lets implement this header file. In Visual Studio select a win32 dll project. The IDE provides you with with example implementations of exported variable, function and a constructor which we can get rid of.
JNIEXPORT jlong JNICALL Java_jniexample_NativeWin32_jniFindWindow (JNIEnv * env, jclass jobj, jstring windowName) { HWND iHwnd; const char *lpWindowName = env->GetStringUTFChars(windowName,0); iHwnd = FindWindow(NULL, (LPCSTR)lpWindowName); return (jlong)iHwnd; } JNIEXPORT jboolean JNICALL Java_jniexample_NativeWin32_jniSetForegroundWindow (JNIEnv *, jclass, jlong jniHwnd) { jboolean foregroundWindowSet = false; if(SetForegroundWindow((HWND)jniHwnd) != 0) { foregroundWindowSet = true; } return foregroundWindowSet; } JNIEXPORT jstring JNICALL Java_jniexample_NativeWin32_jniGetWindowText (JNIEnv * env, jclass, jlong jniHwnd) { PSTR pszMem; int cTxtLen = GetWindowTextLength((HWND)jniHwnd); // Allocate memory for the string and copy // the string into the memory. pszMem = (PSTR) VirtualAlloc((LPVOID) NULL, (DWORD) (cTxtLen + 1), MEM_COMMIT, PAGE_READWRITE); GetWindowText((HWND)jniHwnd, pszMem, cTxtLen + 1); jstring jstrWindowText = env->NewStringUTF((char *)pszMem); VirtualFree(pszMem, 0, MEM_RELEASE); return jstrWindowText; } JNIEXPORT jlong JNICALL Java_jniexample_NativeWin32_jniGetWindow (JNIEnv *, jclass, jlong jniHwnd, jint jniCmd) { HWND iHwnd; iHwnd = GetWindow((HWND)jniHwnd,(int)jniCmd); return (jlong)iHwnd; } JNIEXPORT jboolean JNICALL Java_jniexample_NativeWin32_jniIsWindowVisible (JNIEnv *, jclass, jlong jniHwnd) { jboolean windowVisible = false; if(IsWindowVisible((HWND)jniHwnd) != 0) { windowVisible = true; } return windowVisible; } JNIEXPORT jlong JNICALL Java_jniexample_NativeWin32_jniGetDesktopWindow (JNIEnv *, jclass) { HWND iHwnd; iHwnd = GetDesktopWindow(); return (jlong)iHwnd; }
Compile the project and copy the dll to your java project. Now the native functions can be invoked as normal functions
//Gets the handle to the desktop. long handle = NativeWin32.jniGetDesktopWindow();
You can find the complete source code to the dll here & the java project with compiled binary can be found here.
hello naveed bhai....
ReplyDelete